Bucles en Java
En esta lección
Un bucle repite un bloque de código mientras se cumpla una condición. Gracias a ellos puedes recorrer una lista de alumnos, pedir una contraseña hasta que sea correcta o imprimir una tabla de multiplicar sin escribir diez líneas iguales. Java tiene cuatro bucles: while, do-while, for y for-each. En esta lección aprenderás cuándo usar cada uno, cómo controlarlos con break y continue, y los patrones que se repiten en casi todos los programas: contadores y acumuladores.
while: mientras se cumpla
while comprueba la condición antes de cada vuelta. Si es true, ejecuta el bloque y vuelve a comprobar; si es false, sale.
int numero = 1;
while (numero < 1000) {
numero = numero * 2;
}
System.out.println(numero); // 1024
Úsalo cuando no sabes cuántas vueltas hará falta dar: duplicar hasta pasar de 1000, leer datos hasta que el usuario escriba “fin”, esperar a que algo ocurra.
Si la condición es falsa desde el principio, el bloque no se ejecuta ninguna vez.
Un ejemplo realista: ¿cuántos años tarda en duplicarse un ahorro al 5 % anual?
double saldo = 1000;
int anios = 0;
while (saldo < 2000) {
saldo = saldo * 1.05;
anios++;
}
System.out.println(anios + " años"); // 15 años
do-while: al menos una vez
do-while comprueba la condición al final. Por eso el bloque se ejecuta siempre al menos una vez:
int intentos = 10;
do {
System.out.println("Intento " + intentos); // Intento 10
intentos++;
} while (intentos < 5);
Aunque 10 < 5 es falso, el mensaje se muestra una vez. Es perfecto para menús y para pedir datos hasta que sean válidos, porque primero hay que preguntar y después comprobar:
import java.util.Scanner;
public class PedirNota {
public static void main(String[] args) {
Scanner teclado = new Scanner(System.in);
int nota;
do {
System.out.print("Introduce una nota (0-10): ");
nota = teclado.nextInt();
} while (nota < 0 || nota > 10);
System.out.println("Nota guardada: " + nota);
}
}
Introduce una nota (0-10): 15
Introduce una nota (0-10): -2
Introduce una nota (0-10): 8
Nota guardada: 8
Fíjate en el punto y coma después del while (...) final: es obligatorio. Tienes más sobre Scanner en leer datos por teclado.
for: un número conocido de vueltas
Cuando sabes cuántas veces quieres repetir, for reúne todo el control del bucle en una línea:
for (int i = 1; i <= 5; i++) {
System.out.println("7 x " + i + " = " + (7 * i));
}
7 x 1 = 7
7 x 2 = 14
7 x 3 = 21
7 x 4 = 28
7 x 5 = 35
El paréntesis tiene tres partes separadas por ;:
- Inicio (
int i = 1): se ejecuta una sola vez, antes de empezar. - Condición (
i <= 5): se comprueba antes de cada vuelta. - Paso (
i++): se ejecuta al final de cada vuelta.
Observa los paréntesis en (7 * i): sin ellos, Java concatenaría el texto con el 7 y luego con la i, y verías 7 x 1 = 71.
La variable i solo existe dentro del bucle. Si intentas usarla después, no compila.
El paso puede ser cualquiera: contar hacia atrás, de dos en dos…
for (int i = 10; i > 0; i -= 3) {
System.out.print(i + " "); // 10 7 4 1
}
System.out.println();
Un for es solo una forma compacta de escribir un while. Estos dos bucles hacen exactamente lo mismo:
for (int i = 0; i < 3; i++) {
System.out.println(i);
}
int j = 0;
while (j < 3) {
System.out.println(j);
j++;
}
for-each: recorrer una colección
La forma más cómoda de recorrer todos los elementos de un array o una lista:
String[] frutas = {"manzana", "pera", "kiwi"};
for (String fruta : frutas) {
System.out.println(fruta);
}
manzana
pera
kiwi
Se lee: “para cada fruta de frutas”. No hay índices ni condición, así que es imposible salirse del array. Úsalo siempre que no necesites la posición de cada elemento ni modificar el array. Lo verás mucho en arrays y en ArrayList.
Contadores y acumuladores
Casi todos los bucles que escribirás siguen uno de estos dos patrones:
- Un contador cuenta cuántas veces pasa algo: se inicia a
0y se incrementa con++. - Un acumulador va sumando (o multiplicando) valores: se inicia a
0para sumas y a1para productos.
int[] notas = {7, 4, 9, 5, 3, 8};
int aprobados = 0; // contador
int suma = 0; // acumulador
for (int nota : notas) {
suma += nota;
if (nota >= 5) {
aprobados++;
}
}
double media = (double) suma / notas.length;
System.out.println("Aprobados: " + aprobados); // Aprobados: 4
System.out.println("Media: " + media); // Media: 6.0
Las variables se declaran fuera del bucle. Si las declararas dentro, se reiniciarían en cada vuelta y al salir no existirían.
Otro acumulador clásico, el factorial (5! = 5 × 4 × 3 × 2 × 1):
int n = 5;
long factorial = 1; // producto: empieza en 1, no en 0
for (int i = 2; i <= n; i++) {
factorial *= i;
}
System.out.println(factorial); // 120
break y continue
breaksale del bucle inmediatamente.continuesalta el resto de la vuelta actual y pasa a la siguiente.
for (int i = 1; i <= 20; i++) {
if (i % 3 != 0) {
continue; // si no es múltiplo de 3, pasa a la siguiente vuelta
}
if (i > 12) {
break; // al pasar de 12, sale del bucle
}
System.out.print(i + " "); // 3 6 9 12
}
System.out.println();
break es muy útil para buscar: en cuanto encuentras lo que buscas, no tiene sentido seguir.
String[] usuarios = {"ana", "luis", "marta", "pedro"};
String buscado = "marta";
int posicion = -1;
for (int i = 0; i < usuarios.length; i++) {
if (usuarios[i].equals(buscado)) {
posicion = i;
break;
}
}
System.out.println("Encontrado en " + posicion); // Encontrado en 2
Usar -1 como “no encontrado” es un convenio muy extendido, porque ninguna posición real es negativa.
Bucles anidados
Un bucle dentro de otro. El de dentro da todas sus vueltas por cada vuelta del de fuera. Con dos bucles de 10 vueltas, el bloque interior se ejecuta 100 veces.
Tabla de multiplicar completa
for (int fila = 1; fila <= 4; fila++) {
for (int col = 1; col <= 4; col++) {
System.out.print(fila * col + "\t");
}
System.out.println(); // salto de línea al terminar cada fila
}
1 2 3 4
2 4 6 8
3 6 9 12
4 8 12 16
\t es un tabulador: alinea las columnas.
Patrones con asteriscos
Los ejercicios de dibujar figuras son el mejor entrenamiento para entender los bucles anidados. La clave: el bucle de fuera controla las filas y el de dentro, cuántos símbolos hay en cada fila.
int altura = 4;
for (int fila = 1; fila <= altura; fila++) {
for (int i = 1; i <= fila; i++) { // en la fila 1, un asterisco; en la 2, dos...
System.out.print("*");
}
System.out.println();
}
*
**
***
****
Una pirámide centrada necesita dos bucles interiores: uno para los espacios y otro para los asteriscos.
int altura = 4;
for (int fila = 1; fila <= altura; fila++) {
for (int i = 1; i <= altura - fila; i++) {
System.out.print(" ");
}
for (int i = 1; i <= 2 * fila - 1; i++) {
System.out.print("*");
}
System.out.println();
}
*
***
*****
*******
Consejo: antes de programar una figura, escribe en papel cuántos espacios y cuántos asteriscos lleva cada fila. Busca la fórmula que relaciona esos números con el número de fila y el bucle sale solo.
Etiquetas: salir de varios bucles a la vez
Un break normal solo sale del bucle más interno. Si quieres salir de los dos a la vez, pon una etiqueta al bucle exterior:
int[][] estanterias = {{3, 8, 1}, {4, 7, 9}, {2, 5, 6}};
int buscado = 7;
buscar:
for (int f = 0; f < estanterias.length; f++) {
for (int c = 0; c < estanterias[f].length; c++) {
if (estanterias[f][c] == buscado) {
System.out.println("Está en " + f + "," + c); // Está en 1,1
break buscar;
}
}
}
También existe continue etiqueta, que pasa a la siguiente vuelta del bucle exterior. Úsalas con moderación: a menudo queda más claro sacar la búsqueda a un método y salir con return. Los arrays de dos dimensiones como estanterias se explican en matrices.
Bucles infinitos
Un bucle cuya condición nunca llega a ser falsa no termina nunca. Normalmente es un error:
int i = 0;
while (i < 10) {
System.out.println(i);
// falta i++: i siempre vale 0
}
Si te pasa, detén el programa con Ctrl + C en la terminal o con el botón de parar del IDE.
A veces se escribe un bucle infinito a propósito, con una salida controlada por break. Es habitual en menús:
import java.util.Scanner;
public class Menu {
public static void main(String[] args) {
Scanner teclado = new Scanner(System.in);
while (true) {
System.out.print("Comando (hola/salir): ");
String comando = teclado.nextLine();
if (comando.equals("salir")) {
break;
}
System.out.println("Has escrito: " + comando);
}
System.out.println("Adiós");
}
}
Comando (hola/salir): hola
Has escrito: hola
Comando (hola/salir): salir
Adiós
¿Qué bucle elijo?
| Situación | Bucle |
|---|---|
| Sé cuántas vueltas quiero (o recorro con índice) | for |
| Recorro todos los elementos y no necesito la posición | for-each |
| Repito mientras se cumpla algo, sin saber cuántas veces | while |
| Tengo que ejecutar al menos una vez (menús, validar datos) | do-while |
Errores frecuentes
- Salirse del array:
i <= notas.lengthdaArrayIndexOutOfBoundsException; la condición correcta esi < notas.length. - Punto y coma tras el
for:for (int i = 0; i < 5; i++);repite un bloque vacío y el de debajo se ejecuta una sola vez. - Olvidar actualizar la variable en un
while: bucle infinito. - Declarar el acumulador dentro del bucle: se reinicia en cada vuelta.
- Empezar un producto en 0: cualquier cosa multiplicada por 0 es 0.
Resumen
whilecomprueba antes;do-whilecomprueba después y se ejecuta al menos una vez.for (inicio; condición; paso)es ideal cuando conoces el número de vueltas.- for-each (
for (Tipo x : coleccion)) recorre todos los elementos sin índices. breaksale del bucle;continuesalta a la siguiente vuelta; con etiquetas afectan a un bucle exterior.- Contadores (
++) y acumuladores (+=) se declaran fuera del bucle. - En bucles anidados, el interior da todas sus vueltas por cada vuelta del exterior.
Ahora que sabes repetir operaciones, es el momento de trabajar a fondo con el texto: String y StringBuilder.
Pon a prueba lo que has aprendido
¿Te ha quedado claro? Márcala y verás tu progreso en el explorador.