Saltar al contenido
bucles.java · devschool

Bucles en Java

Lección 6 de 26 · 10 min de lectura · Actualizado el

En esta lección
  1. while: mientras se cumpla
  2. do-while: al menos una vez
  3. for: un número conocido de vueltas
  4. for-each: recorrer una colección
  5. Contadores y acumuladores
  6. break y continue
  7. Bucles anidados
  8. Etiquetas: salir de varios bucles a la vez
  9. Bucles infinitos
  10. ¿Qué bucle elijo?
  11. Errores frecuentes
  12. Resumen

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 ;:

  1. Inicio (int i = 1): se ejecuta una sola vez, antes de empezar.
  2. Condición (i <= 5): se comprueba antes de cada vuelta.
  3. 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 0 y se incrementa con ++.
  • Un acumulador va sumando (o multiplicando) valores: se inicia a 0 para sumas y a 1 para 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

  • break sale del bucle inmediatamente.
  • continue salta 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ónBucle
Sé cuántas vueltas quiero (o recorro con índice)for
Recorro todos los elementos y no necesito la posiciónfor-each
Repito mientras se cumpla algo, sin saber cuántas veceswhile
Tengo que ejecutar al menos una vez (menús, validar datos)do-while

Errores frecuentes

  • Salirse del array: i <= notas.length da ArrayIndexOutOfBoundsException; la condición correcta es i < 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

  • while comprueba antes; do-while comprueba 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.
  • break sale del bucle; continue salta 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

[Java] ¿Cuántas veces se ejecuta el bloque?
int i = 10;
do {
  System.out.println(i);
  i++;
} while (i < 5);

[Java] ¿Cuántos asteriscos imprime este código?
for (int i = 0; i < 3; i++) {
    for (int j = 0; j < 4; j++) {
        System.out.print("*");
    }
}

[Java] ¿Qué imprime este código?
int suma = 0;
for (int i = 1; i <= 6; i++) {
    if (i == 3) {
        continue;
    }
    if (i == 5) {
        break;
    }
    suma += i;
}
System.out.println(suma);

¿Te ha quedado claro? Márcala y verás tu progreso en el explorador.