4 formas de hacer un bucle for en Java

Escrito por el , actualizado el .
blog-stack java planeta-codigo programacion
Comentarios

La forma habitual en Java de hacer un bucle es con una sentecia for o while pero con el añadido de los iteradores en Java 5 no hace falta tener una variable para conservar el índice del bucle. Ya en Java 8 se han añadido los streams que ofrecen otras nuevas formas de iterar sobre los elementos de una colección en este último caso con técnicas propias de lenguajes funcionales.

Java

Hasta Java 5 para hacer un bucle desde 0 a N elementos había que usar una variable para mantener un contador, hacer una comparación para comprobar si se había llegado al límite e incrementar la variable en la siguiente ejecución. El código era bastante verboso y dado que los bucles son una construcción básica de cualquier lenguaje de programación es empleada numerosas veces en cualquier algoritmo. Antes de Java 5 un bucle for de 0 a 5 y de una colección se realizaba de la siguiente manera:

1
2
3
for (int i = 0; i < 5; ++i) {
    System.out.println(i);
}
1
2
3
4
5
Collection<Integer> = Arrays.asList(0, 1, 2, 3, 4);
Iterable it = collection.iterable();
while (it.hasNext()) {
    System.out.println(it.next());
}

En Java 5 el bucle for se enriqueció notablemente, con el foreach se puede recorrer una colección y cualquier objeto que implemente la interfaz Iterable. Con el bucle foreach una Collection se recorre de la siguiente manera.

1
2
3
for (int i : Arrays.asList(0, 1, 2, 3, 4)) {
    logger.info("{}", i);
}

Pero esto es para las colecciones si se quiere hacer un bucle un número fijo de veces como en el primer caso de 0 a 5 conociendo que para usar el foreach basta que le indiquemos un objeto que implemente la interfaz Iterable podemos usar la siguiente expresión y su implementación que tiene la ventaja de no tener que incluir la expresión de comparación y el incremento de la variable, la clase Counter implementa la interfaz Iterable y devuelve un Iterator sobre los valores del rango indicado:

1
2
3
for (Object i : new Counter(0, 5)) {
    System.out.println(i);
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package io.github.picodotdev.blogbitix.javaforeach;

import java.util.Iterator;

public class Counter implements Iterable<Integer> {

    private int start;
    private int end;

    public Counter(int start, int end) {
        this.start = start;
        this.end = end;
    }

    public Iterator<Integer> iterator() {
        return new Iterator<Integer>() {
            private int i = start;

            public boolean hasNext() {
                return i < end;
            }

            public Integer next() {
                return i++;
            }

            public void remove() {
                throw new UnsupportedOperationException();
            }
        };
    }
}

En Java 8 con la introducción de los Stream y de IntStream podemos usar el método range y rangeClosed para obtener un Stream de enteros y hacer un bucle con un comportamiento similar a los anteriores.

1
2
3
IntStream.range(0, 5).forEach( i -> {
    System.out.println(i);
});

Los Stream de Java 8 están muy bien para simplificar algunas operaciones complejas pero para un bucle for sencillo tiene sus inconvenientes como ofuscar significativamente el stacktrace en caso de producirse alguna excepción. Se puede usar cualquier opción pero la primera con el tradicional bucle for sea la menos recomendable teniendo a nuestra disposición la clase Counter con Java 5 o los Stream y lambdas con Java 8.

El siguiente programa muestra las cuatro opciones, su salida en la consola sería el siguiente:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package io.github.picodotdev.blogbitix.javaforeach;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Arrays;
import java.util.stream.IntStream;

public class Main {

    private static Logger logger = LoggerFactory.getLogger(Main.class);

    public static void main(String[] args) {
        logger.info("for i");
        for (int i = 0; i < 5; i++) {
            logger.info("{}", i);
        }

        logger.info("foreach");
        for (int i : Arrays.asList(0, 1, 2, 3, 4)) {
            logger.info("{}", i);
        }

        logger.info("for counter");
        for (int i : new Counter(0, 5)) {
            logger.info("{}", i);
        }

        logger.info("stream foreach");
        IntStream.range(0, 5).forEach(i -> {
            logger.info("{}", i);
        });
    }
}
4 formas de hacer un bucle en Java

El código fuente completo del ejemplo puedes descargarlo del repositorio de ejemplos de Blog Bitix alojado en GitHub y probarlo en tu equipo ejecutando el comando ./gradlew run.