Bucles e Iteradores en Java

Los bucles en Java son 3: while, do, y for (Y a partir de Java 6, el bucle for tiene 2 variaciones). Estos 3 bucles nos permiten repetir un bloque de código tantas veces como una condición sea true, o para un número de iteraciones específicas. Probablemente ya tengamos familiarizados los bucles en otros lenguajes, por lo que no supondrá un problema aprenderlos en Java.


  • Usando bucles while

    El bucle while es bueno para escenarios donde no sabemos cuantas veces el un bloque o sentencia se debe repetir, pero queremos que continúe repitiendolo mientras una condición sea true. Una sentencia while se parece a lo siguiente:

    		while (expresion) {
    			// hacer cosas
    		}
    		
    		int x = 2;
    		while (x == 2) {
    			System.out.println(x);
    			++x;
    		}
    		

    En este caso, como en todos los bucles, la expresión debe evaluarse a un resultado booleano. EL cuerpo del bucle while solo se ejecuta si la expresión (o condicion tambien llamado) da como resultado un true. Una vez que estamos dentro del bucle, el cuerpo del bucle se repetirá hasta que la condición no sea true, es decir, cuando la condición se evalúe a false. En el anterior ejemplo, el programa entrará al cuerpo del bucle porque x es igual a 2. Sin embargo, x es incrementado dentro del bucle, por lo que cuando al condición sea comprobada de nuevo, se evaluará a false y saldrá del bucle.

    cualquier variable usada en la expresión de un bucle while debe ser declarada antes de que sea evaluada. En otras palabras, no podemos hacer lo siguiente:

    		while (int x = 2) { } // No es legal
    		

    Por otra parte, ¿Por lo haría? En vez de comprobar la variable, estaríamos declarandola e inicializandola, por lo que el valor sería siempre exactamente el mismo. No es una expresión que podamos evaluar a true o false.

    El punto clave que tenemos que recordar sobre el bucle while es que nunca se ejecute. Si un test de la expresión es false la primera vez que se comprueba la expresion del while, el cuerpo del bucle no se ejecutará y el programa empezará a ejecutar la primera sentencia despues del bucle while. Miremos los siguientes ejemplos:

    		int x = 8;
    		while (x > 8) {
    			System.out.println("Dentro del bucle");
    			x = 10;
    		}
    		System.out.println("Pasado el bucle");
    		

    Si ejecutamos este código obtendremos: “Pasado el bucle”, ya que la expresión (x > 8) se evalúa a false, por lo tanto ningún código dentro del bucle se ejecutará nunca.

  • Usando bucles do

    El bucle do es similar al bucle while, excepto porque la expresión no es evaluada hasta que el código dentro del bucle se ha ejecutado. Por lo tanto el código en un bucle do tiene la garantía de ejecutarse al menos una vez. Lo siguiente es un ejemplo del uso de un bucle do en acción:

    		do {
    			System.out.println("Dentro del loop");
    		}while (false);
    		

    La sentencia “System.out.println() se imprimirá una vez, incluso aunque al expresión sea false. recordemos, que el bucle do siempre ejecutará el cuerpo del bucle al menos una vez. Tenemos que estar seguros de que el while al final del bucle tiene punto y coma “;”.

  • Usando bucle for

    A partir de Java 6, el bucle for tiene una estructura secundaria. Llamaremos al viejo estilo de bucle for como “bucle for básico”, y llamaremos al nuevo estilo “bucle for mejorado”. Dependiendo de la documentación que usemos, veremos diferentes términos para determinar el bucle for mejorado, como for-in, El término for-in, for-each y for mejorado se refieren a la misma construcción en Java.

    El bucle for básico es mas flexible que el bucle for mejorado, pero el bucle for mejorado está diseñado para iterar a través de arrays y colecciones de una manera mas facil en el código.

    • El bucle for básico

      El bucle for es especialmente útil para el control del flujo cuando ya sabemos cuantas veces tenemos que ejecutar las sentencias que se encuentran en el interior del bloque del bucle. La declaración del bucle for tiene 3 partes principales, junto al cuerpo del bucle:

      • Declaración e inicialización de variables.
      • Expresion booleana (test condicional).
      • Expresión de iteración.

      Las 3 partes de declaración en un bucle for están separadas por punto y coma “;”. Los siguientes 2 ejemplos demuestran un bucle for. El primer ejemplo muestra las partes del bucle for en forma de pseudocódigo, y la segunda nos muestra un ejemplo típico del bucle.

      				for (/*Inicialización*/ ; /*Condicion*/ ; /*Iteracion*/) {
      					/* Cuerpo del bucle */
      				}
      				
      				for (int 0 0; i < 10; i++){
      					System.out.println("i es " + i);
      				}
      				
    • Bucle for básico: Declaración e Inicialización

      La primera parte de una sentencia for nos permite declarar e inicializar a 0, una o mas variables del mismo tipo dentro del parentesis despues de la palabra clave for. Si declaramos mas de una variable del mismo tipo, entonces tendremos que separarlas con comas como en el siguiente ejemplo:

      				for (int x = 10, y = 3; y > 3; y++){ }
      				

      La declaración e inicialización ocurre antes que cualquier otra cosa en el bucle for. Mientras que las otras 2 partes, el test booleano y la expresión de iteración, se ejecutarán con cada iteración del bucle. La declaración e inicialización ocurre solo una vez, al comienzo. Debemos saber tambien que el ámbito de las variables declaradas en el bucle for termina con el bucle for. Lo siguiente demuestra esto:

      				for (int x = 1; x < 2; x++){
      					System.out.println(x); // Legal
      				}
      				System.out.println(x); // No es legal!, x está fuera del ámbito y no puede ser accedido
      				

      Si intentamos compilar esto, obtendremos un error que nos indicará que la variable x no puede ser usada o no existe.

    • Bucle for básico: Expresión Condicional (boolean)

      La siguiente sección que se ejecuta es al expresión condicional, la cual debe evaluar un valor boolean. Podemos tener solo una expresión logica, pero puede ser muy compleja. Veamos el siguiente código que usa una expresión lógica como la siguiente:

      				for (int x = 0; ((((x < 10) && (y-- > 2)) | x == 3)); x++) { }
      				

      El ejemplo anterior es legal, pero el siguiente no lo es:

      				for (int x = 0; (x > 5), (y < 2); x++){ } // Demasiadas expresiones
      				

      El compilador nos hará saber cuál es el problema.

      En otras palabras, no podemos usar multiples test separados por comas, incluso aunque las otras partes en una sentencia for puedan tener múltiples partes, en el caso de la evaluación de una condición, esta debe constar solo de 1 expresión, aunque sea muy compleja.

    • Bucle for básico: Expresión de Iteración

      Después de cada ejecución del cuerpo de un bucle for, la expresión de iteración es ejecutada. Aquí es donde podemos decur que queremos que pase con cada iteración del bucle. Recordemos que siempre ocurre después de que el cuerpo del bucle se ejecute. Veamoslo en el ejemplo siguiente:

      				for (int x = 0; x < 1; x++){
      					// El cuerpo del código que no cambia el valor de x
      				}
      				

      El anterior bucle se ejecuta solo 1 vez. La primera vez que se entra al bucle, x es establecido a 0, entonces se comprueba si x es menor que 1, y después el cuerpo del bucle se ejecuta. Después de que el cuerpo del bucle se ejecute, la expresión de iteración se ejecuta, incrementando x en 1. Lo siguiente que se ejecuta es el test condicional, y ya que el resultado es false, la ejecución salta a la siguiente sentencia inmediatamente después del bucle for.

      Los ejemplos de una salida forzada incluyen las palabras clave break, return, o un System.exit(), o una excepción, lo cual causará que el bucle se termine abruptamente, sin ejecutar la expresión de iteración. Veamos el siguiente código:

      				static boolean doStuff() {
      					for (int x = 0; x < 3; x++){
      						System.out.println("Dentro del bucle for");
      						return true;
      					}
      					return true;
      				}
      				

      Si ejecutamos este ejemplo obtendríamos: “Dentro del bucle for”. La sentencia solo se imprime una vez, ya que el return hace que la ejecución no salga solo del bucle for, sino del método en sí. Por lo tanto, la expresión de iteración nunca se ejecuta en este caso. EN la siguiente tabla podemos ver las causas y resultados de una terminación abrupta:

      Código en el bucle Lo que pasa
      break La ejecución salta inmediatamente a la primera sentencia después del bucle for
      return La ejecución salta inmediatamente al método que lo llame
      System.exit() Toda ejecución del programa se para; La VM se apaga.
    • Bucle for básico: Cuestiones sobre el bucle for

      Ninguna de las 3 secciones en la declaración de un bucle son requeridas. El siguiente ejemplo es perfectamente legal (Aunque no es una buena práctica):

      				for ( ; ; ){
      					System.out.println("Dentro de un bucle infinito");
      				}
      				

      En el anterior ejemplo, todas las partes de la declaración se han dejado en blanco, por lo que el bucle for será un bucle infinito. Es importante saber que al ausencia de las secciones de inicialización, el bucle actúa como un bucle while. El siguiente ejemplo demuestra como se logra esto:

      int i = 0;

      for (;i < 10;){
      i++;
      // Hacer otras cosas
      }

      El siguiente ejemplo demuestra un bucle for con múltiples variables en juego. Variables separadas por comas, deben ser siempre del mimo tipo. Recordemos que las variables declaradas en una sentencia for son locales para el bucle for, y no pueden ser usadas fuera del ámbito del bucle for.

      				for (int i = 0, j = 0; (i &lt; 10); i++, j++){
      					System.out.println(&quot;i es &quot; + i + &quot; j es &quot; + j);
      				}
      				

      La última cosa para la que tenemos que tomar nota es que todas estas 3 secciones en el bucle for son independientes las unas de las otras. Las 3 expresiones en la sentencia for no necesitan operar con las mismas variables, aunque lo hagan normalmente. Pero incluso la expresión de iteracion, el cuál puede llamarse por error “expresión de incremento”, no necesita incrementar o establecer nada; podemos poner virtualmente y arbitrariamente sentencias de código que queramos que ocurra con cada iteración del bucle. Veamos lo siguiente:

      				int b = 3;
      				for (int a = 1; b != 1; System.out.println(&quot;Iteracion&quot;)){
      					b = b - a;
      				}
      				

      El anterior código imprimirá 2 veces la palabra “Iteracion”.

    • El bucle for mejorado (para Arrays)

      El bucle for mejorado, nuevo en Java 6, es un bucle for especializado que simplifica la iteración a través de un array o una colección. En este capítulo vamos a centrarnos en la iteración a través de arrays usando el bucle for mejorado.

      En vez de tener 3 componentes, el for mejorado tiene solo 2. Vamos a iterar a través de un array de la manera básica o antigua, y luego usaremos el for mejorado:

      				int[] a = {1, 2, 3, 4};
      				for (int x = 0; x &lt; a.length; x++){
      					System.out.println(a[x]);	// Bucle for básico
      				}
      				
      				for (int n : a){
      					System.out.println(n);	// Bucle for mejorado
      				}
      				

      Esto producirá la siguiente salida: 12341234

      De manera mas formal, vamos a describir el for mejroado como lo siguiente:

      				for (declaration : expression)
      				

      Las 2 piezas de la sentencias son:

      • Declaracion: La nueva variable de bloque declarada, de un tipo compatible con los elementos del array al que estemos accediendo. Esta variable estará disponible dentro del bloque for, y su valor será el mismo que el actual elemento del array.
      • Expresion: Esto debe evaluar al array que queramos acceder. Puede ser una variable de array o una llamada a un método que retorne un array. El array puede ser de cualqueir tipo: primitivos, objetos, incluso arrays de arrays.

      Usando las definiciones que tenemos encima, vamos a ver algunos ejemplos legales e ilegales de declaraciones de bucle for:

      				int x;
      				long x2;
      				Long[] La = {4L, 5L, 6L};
      				long[] la = {7L, 8L, 9L};
      				int[][] twoDee = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
      				String[] sNums = {&quot;one, &quot;two&quot;, &quot;three&quot;};
      				Animal[] animals = {new Dog(), new Cat()};
      				
      				// Declaraciones legales de for
      				for (long y : la);			// Iteraciona en un array de longs
      				for (long lp : La);			// autoboxing de objetos Long en longs
      				
      				for (int[] n : twoDee);		// Iteraciones en el array de arrays
      				for (int n2 : twoDee[2]);	// Iteraciones el tercer subarray
      				for (String s : sNums);		// Iteraciones en el array de Strings
      				for (Object o : sNums);		// Establece uan referencia a objeto de cada String
      				
      				for (Animal a : animals);	// Establece una referencia de Animal a cada elemento
      				
      				// Declaraciones ILEGALES de for
      				for (x2 : la);				// x2 ya ha sido declarado
      				for (int x2 : twoDee);		// no podemos meter un array en un int
      				for (int x3 : la);			// No podemos meter un long en un int
      				for (Dog d : animals);		// No podemos obtener un Cat
      				

      El bucle for mejorado asume que, excepto una salida temprana en un bucle, siempre hará una iteración pro cada elemento del array.

  • Usando break y continue

    Las palabras clave break y continue son usadas para parar o el bucle entero (break) o la iteración actual (continue). Típicamente si usamos break o continue, haremos un test if dentro del bucle, y si alguna condición se convierte en true (o false dependiendo del programa), querremos salir inmediatamente. La diferencia entre ellos es que con uno saldremos de la iteración actual para continuar con la siguiente, y con el otro saltaremos inmediatamente a la primera sentencia que exista después del bucle for.

    La sentencia break causa que el programa pare su ejecución del bucle mas cercano y comience el procesamiento de la siguiente línea de código después del bloque.

    La sentencia continue hace que solo la iteracion actual del loop mas cercano cese y una nueva iteración en el mismo bucle comience si la condición del loop se dá. Cuando usamos la sentencia continue con un bucle for, tenemos que considerar los efectos que puede tener el continue en la iteración del bucle. Veamos el siguiente código:

    		for (int i = 0; i &lt; 10; i++){
    			System.out.println(&quot;Dentro del loop&quot;);
    			continue;
    		}
    		

    La pregunta es, ¿Es un bucle infinito? La respuesta es no. Cuando la sentencia continue se ejecuta, expresión de iteración se sigue ejecutando. Se ejecuta como si la iteración termianra de forma natural. Por lo que ene l ejemplo anterior, seguiría incrementandose antes de que la condición (< < 10) se comprobara de nuevo. La mayoría de las veces, un continue es usado dentro de un test if como lo siguiente:

    		for (int i = 0; i &lt; 10; i++){
    			System.out.println(&quot;Dentro del loop&quot;);
    			if (foo.doStuff() == 5){
    				continue;
    			}
    			// Mas código del loop, no será ejecutado cuando el test f sea true.
    		
  • Sentencias sin etiqueta

    Tanto la sentencia break como continue pueden tener una etiqueta o no tenerla. Como hemos dicho antes, una sentencia break (sin etiqueta) saldrá de la construcción del bucle mas cercano y procederá con la siguiente línea de código mas allá de l bloque del bucle. El siguiente ejemplo demuestra una sentencia break:

    		boolean problem = true;
    		while (true){
    			if (problem){
    				System.out.println(&quot;Había un problema&quot;);
    				break;
    			}
    		}
    		// Siguiente línea de código
    		

    En el ejemplo anterior, la sentencia break está sin etiquetar. Lo siguiente es un ejemplo de una sentencia continua sin etiquetar:

    		while (!EOF){
    			// se lee un campo de un archivo
    			if (wrongField){
    				continue;		// se mueve al siguiente campo en el archivo
    			}
    			// De otro modo, se hace otra cosa con el campo
    		}
    		

    En este ejemplo, un campo del archivo se estará leyendo en cada iteración. Cuando se encuentre un error, el programa se moevrá al campo siguiente ene la rchivo y usará la sentencia continue para volver al bucle (si no está en el fin del archivo) y seguirá leyendo los diferentes campos. La sentencia continue nos da una manera de decir, “Esta iteración en particular tiene que parar, pero no el bucle entero. No quiero que el resto de código en la iteración termine, por lo que haz la expresión de iteración y comienza con el test, y no nos preocupemos sobre lo que hay debajo de la sentencia continue.

  • Sentencias con etiqueta

    Aunque varias sentencias en un programa Java pueden ser etiquetadas, es mas común usar etiquetas en bucles como for o while, en conjunción de sentencias break y continue. Una sentencia de etiqueta debe ser colocada justo antes de la sentencia que se va a etiquetar, y consiste en un identificador válido que termina con 2 puntos “:”

    Tenemos que entender la diferencia entre sentencias break y continue etiquetadas o sin etiquetar. Las variedades etiquetadas son necesarias solo para situaciones donde tenemos bucles enlazados, y tenemos que indicar cual de los bucles enlazados queremos parar, o de que bucle enlazado queremos continuar con la siguiente iteración. Una sentencia break saldrá solo del bucle etiquetado, en oposición al bucle mas cercano, si la palabra clave break se combina con una etiqueta. Un ejemplo de como se ve una etiqueta lo podemos ver en el siguiente ejemplo:

    		foo:
    			for (int x = 3; x &lt; 20; x++){
    				while (y &gt; 7) {
    					y--;
    				}
    			}
    		

    La etiqueta debe adherirse a las reglas para un nombre de variable y debe aderirse a las convenciones de nomenclatura de Java. La sintaxis para el uso de un nombre de etiqueta en conjunción con una sentencia break es la palabra break, luego el nombre de la etiqueta, seguido de 2 puntos “:”. Un ejemplo mas completo del uso de una sentencia break etiquetada es el siguiente:

    		boolean isTrue = true;
    		outer:
    			for (int i= 0; i &lt; 5; i++){
    				while (isTrue){
    					System.out.println(&quot;Hello&quot;);
    					break outer;
    				} // Final del primer bucle while
    				System.out.println(&quot;Bucle exterior,&quot;); // No se imprimirá
    			} // Fin del bucle outer
    		System.out.println(&quot;Good-Bye&quot;);
    		

    Si ejecutamos este código producirá la salida:

    		Hello
    		Good-Bye
    		

    Ene ste ejemplo la palabra Hello se imprimirá una vez. Entonces, la sentencia break etiquetada será ejecutada, y el flujo saldrá del bucle etiquetado como outer. La siguiente línea de código entonces imprimirá Good-Bye. Vamos a ver que pasaría si la sentencia continue es usada en vez de la sentencia break. El siguiente ejemplo de código es similar al anterior, con la excepción de sustituir el continue por el break:

    		outer:
    			for (int i = 0; i &lt; 5; i++){
    				for (int j = 0; j &lt; 5; j++){
    					System.out.println(&quot;Hello&quot;);
    					continue outer;
    				} // Fin del bucle interior
    				System.out.println(&quot;outer&quot;); // Nunca se ejecuta
    			}
    		System.out.println(&quot;Good-Bye&quot;);
    		

    Si ejecutamos este código obtendremos la salida:

    		Hello
    		Hello
    		Hello
    		Hello
    		Hello
    		Good-Bye
    		

    En este ejemplo, Hello se imprimirá 5 veces. Después de que la sentencia continue se ejecute, el flujo continua con la siguiente iteración del bucle idetificado en la etiqueta. Finalmente, cuando la condición del bucle outer es evaluada a false, este bucle finalizará y Good-Bye será mostrado en pantalla.


En esta entrada hemos visto el uso de los bucles while, do y for, este último en sus 2 variantes. Hemos entendido su funcionamiento, y con ello podemos sacar en claro en que situaciones podemos usarlos.

Sin mas, cualquier aporte o corrección es bienvenido.

Saludos!!!

  • Mario

    Excelente artículo, gracias. Solo falta el nombre de la variable del bucle for cuando la declaras/inicializas en el ejemplo de la sentencia break.
    Excelente artículo!

  • Mario

    El break con etiqueta, saludos y de nuevo Gracias