Estructuras de control - parte 2

Básico
Java
Java
Actualizado: 27/04/2026

Estructuras de control 2: bucles

flowchart TB
    Loop[Bucles] --> While[while]
    Loop --> Do[do while]
    Loop --> For[for clásico]
    Loop --> Each[for each enhanced]
    Loop --> Stream[Stream API funcional]
    Loop --> Jump[Saltos]
    Jump --> Brk[break label]
    Jump --> Cont[continue label]
    Jump --> Ret[return]
    Loop --> IntStr[IntStream range]

Control iterativo con for

Las estructuras de control iterativas, también conocidas como bucles, permiten ejecutar un bloque de código repetidamente mientras se cumpla una condición determinada. El bucle for es una de las estructuras de iteración más utilizadas en Java, especialmente cuando se conoce de antemano el número de iteraciones a realizar.

Sintaxis básica del bucle for

La estructura básica del bucle for consta de tres partes principales:

for (inicialización; condición; actualización) {
    // Código a ejecutar en cada iteración
}
  • Inicialización: Se ejecuta una sola vez al principio y generalmente se utiliza para declarar e inicializar una variable de control.
  • Condición: Se evalúa antes de cada iteración. Si es true, se ejecuta el bloque de código; si es false, el bucle termina.
  • Actualización: Se ejecuta después de cada iteración y normalmente se utiliza para modificar la variable de control.

Veamos un ejemplo básico:

for (int i = 0; i < 5; i++) {
    System.out.println("Iteración número: " + i);
}

En este ejemplo:
1. Se inicializa i con el valor 0

2. Se verifica si i es menor que 5

3. Si la condición es verdadera, se ejecuta el bloque de código

4. Después de la ejecución, se incrementa i en 1

5. Se vuelve al paso 2 y se repite el proceso hasta que i ya no sea menor que 5

La salida sería:

Iteración número: 0
Iteración número: 1
Iteración número: 2
Iteración número: 3
Iteración número: 4

Variaciones del bucle for

Decrementos en lugar de incrementos

Se puede iterar en orden descendente utilizando decrementos:

for (int i = 10; i > 0; i--) {
    System.out.println("Cuenta regresiva: " + i);
}
System.out.println("¡Despegue!");

Incrementos/decrementos diferentes a 1

No es necesario incrementar o decrementar de uno en uno:

// Mostrar los números pares del 0 al 20
for (int i = 0; i <= 20; i += 2) {
    System.out.print(i + " ");
}
// Salida: 0 2 4 6 8 10 12 14 16 18 20

Múltiples variables de control

Se pueden utilizar múltiples variables en un bucle for:

for (int i = 1, j = 10; i <= 10 && j >= 1; i++, j--) {
    System.out.println("i = " + i + ", j = " + j);
}

En este ejemplo, i se incrementa mientras que j se decrementa en cada iteración.

Omitir partes del for

Cualquiera de las tres partes del bucle for puede omitirse, aunque los puntos y comas son obligatorios:

// Inicialización fuera del bucle
int i = 0;
for (; i < 5; i++) {
    System.out.println(i);
}

// Actualización dentro del bloque
for (int j = 0; j < 5;) {
    System.out.println(j);
    j++;
}

// Bucle infinito (la condición siempre es verdadera)
for (;;) {
    System.out.println("Bucle infinito");
    // Necesita una condición de salida interna
    break; // Sale del bucle
}

Bucle for-each (enhanced for)

Java ofrece una versión mejorada del bucle for, conocida como bucle for-each, que simplifica la iteración sobre colecciones y arrays:

for (tipo nombreVariable : colección) {
    // Código a ejecutar para cada elemento
}

Este tipo de bucle es más conciso y menos propenso a errores cuando solo se necesita acceder a los elementos sin modificar la colección:

String[] frutas = {"Manzana", "Plátano", "Naranja", "Fresa"};

// Bucle for tradicional
for (int i = 0; i < frutas.length; i++) {
    System.out.println("Me gusta la " + frutas[i]);
}

// Bucle for-each (más simple)
for (String fruta : frutas) {
    System.out.println("Me gusta la " + fruta);
}

El bucle for-each es especialmente útil con colecciones como ArrayList, Set, etc.:

import java.util.List;
import java.util.ArrayList;

List<Integer> numeros = new ArrayList<>();
numeros.add(1);
numeros.add(2);
numeros.add(3);

for (Integer numero : numeros) {
    System.out.println("Número: " + numero);
}

Limitaciones del bucle for-each

Aunque el bucle for-each es más simple, tiene algunas limitaciones:

  • No permite modificar la colección durante la iteración
  • No proporciona acceso al índice del elemento actual
  • No permite iterar en orden inverso fácilmente
  • No permite iterar sobre múltiples colecciones simultáneamente
// Si necesitas el índice, usa el for tradicional
String[] nombres = {"Ana", "Carlos", "Elena"};
for (int i = 0; i < nombres.length; i++) {
    System.out.println("Posición " + i + ": " + nombres[i]);
}

Control de flujo dentro de bucles

Dentro de cualquier bucle, incluido el for, se pueden utilizar las instrucciones break y continue para controlar el flujo de ejecución:

  • break: Termina el bucle inmediatamente y continúa con el código después del bucle.
  • continue: Salta a la siguiente iteración del bucle, omitiendo el resto del código en la iteración actual.
// Uso de break
for (int i = 1; i <= 10; i++) {
    if (i == 5) {
        System.out.println("Encontrado el 5, saliendo del bucle");
        break;
    }
    System.out.println("Número: " + i);
}

// Uso de continue
for (int i = 1; i <= 10; i++) {
    if (i % 2 == 0) {
        // Salta los números pares
        continue;
    }
    System.out.println("Número impar: " + i);
}

Bucles anidados

Se pueden anidar bucles for para trabajar con estructuras de datos multidimensionales o para resolver problemas más complejos:

// Tabla de multiplicar
for (int i = 1; i <= 10; i++) {
    for (int j = 1; j <= 10; j++) {
        System.out.printf("%4d", i * j);
    }
    System.out.println(); // Nueva línea después de cada fila
}

Este código genera una tabla de multiplicar del 1 al 10. El bucle externo controla las filas, mientras que el bucle interno controla las columnas.

Etiquetas en bucles

Java permite etiquetar bucles, lo que es útil cuando se trabaja con bucles anidados y se necesita salir de un bucle específico:

externo: for (int i = 0; i < 5; i++) {
    interno: for (int j = 0; j < 5; j++) {
        if (i * j > 6) {
            System.out.println("Saliendo del bucle externo cuando i=" + i + ", j=" + j);
            break externo; // Sale del bucle etiquetado como "externo"
        }
        System.out.println("i=" + i + ", j=" + j);
    }
}

En este ejemplo, cuando el producto i * j supera 6, se utiliza break externo para salir completamente del bucle externo, no solo del bucle interno.

Casos de uso comunes

Iteración sobre arrays

int[] numeros = {10, 20, 30, 40, 50};
int suma = 0;

for (int numero : numeros) {
    suma += numero;
}

System.out.println("La suma es: " + suma);

Generación de patrones

// Patrón de triángulo
for (int i = 1; i <= 5; i++) {
    for (int j = 1; j <= i; j++) {
        System.out.print("* ");
    }
    System.out.println();
}

Salida:

* 
* * 
* * * 
* * * * 
* * * * * 

Búsqueda en arrays

int[] valores = {15, 7, 23, 9, 4, 12};
int buscar = 9;
boolean encontrado = false;

for (int i = 0; i < valores.length; i++) {
    if (valores[i] == buscar) {
        System.out.println("Valor encontrado en la posición: " + i);
        encontrado = true;
        break;
    }
}

if (!encontrado) {
    System.out.println("Valor no encontrado");
}

Buenas prácticas

  • Nombres descriptivos: Utilizar nombres significativos para las variables de control.
  • Simplicidad: Mantener el cuerpo del bucle lo más simple posible.
  • Evitar modificaciones: No modificar la variable de control dentro del cuerpo del bucle.
  • Preferir for-each: Usar el bucle for-each cuando sea posible para mayor claridad.
  • Verificar límites: Asegurarse de que los índices no excedan los límites del array.
// Mal ejemplo
for (int i = 0; i < array.length; i++) {
    // Modificar i dentro del bucle puede causar comportamientos inesperados
    if (condición) i += 2;
}

// Buen ejemplo
for (int índice = 0; índice < array.length; índice++) {
    // Cuerpo del bucle sin modificar índice
}

Control iterativo con while y do while

Los bucles while y do-while son estructuras de control iterativas que permiten ejecutar un bloque de código repetidamente mientras se cumpla una condición específica. A diferencia del bucle for, que se utiliza principalmente cuando se conoce el número de iteraciones de antemano, los bucles while y do-while son más adecuados cuando el número de iteraciones depende de una condición que puede cambiar durante la ejecución.

Bucle while

El bucle while evalúa una condición antes de ejecutar el bloque de código. Si la condición es verdadera, se ejecuta el bloque y luego se vuelve a evaluar la condición. Este proceso se repite hasta que la condición se vuelve falsa.

La sintaxis básica es:

while (condición) {
    // Código a ejecutar mientras la condición sea verdadera
}

Veamos un ejemplo sencillo:

int contador = 1;

while (contador <= 5) {
    System.out.println("Contador: " + contador);
    contador++;
}

En este ejemplo:
1. Se inicializa contador con el valor 1

2. Se verifica si contador es menor o igual a 5

3. Si la condición es verdadera, se ejecuta el bloque de código

4. Se incrementa contador en 1

5. Se vuelve al paso 2 y se repite el proceso hasta que contador ya no sea menor o igual a 5

La salida sería:

Contador: 1
Contador: 2
Contador: 3
Contador: 4
Contador: 5

Características importantes del bucle while

  • La condición se evalúa antes de cada iteración
  • Si la condición es falsa desde el principio, el bloque de código no se ejecuta ni una sola vez
  • Es necesario modificar alguna variable dentro del bucle para que la condición eventualmente se vuelva falsa, de lo contrario se crea un bucle infinito
// Ejemplo de bucle infinito (¡cuidado!)
while (true) {
    System.out.println("Este mensaje se imprimirá indefinidamente");
    // Necesita una condición de salida interna
    if (algún criterio) {
        break; // Sale del bucle
    }
}

Bucle do-while

El bucle do-while es similar al while, pero con una diferencia crucial: la condición se evalúa después de ejecutar el bloque de código, lo que garantiza que el bloque se ejecute al menos una vez, incluso si la condición es falsa desde el principio.

La sintaxis básica es:

do {
    // Código a ejecutar al menos una vez
} while (condición);

Veamos un ejemplo:

int contador = 1;

do {
    System.out.println("Contador: " + contador);
    contador++;
} while (contador <= 5);

La salida sería la misma que en el ejemplo anterior:

Contador: 1
Contador: 2
Contador: 3
Contador: 4
Contador: 5

Pero observemos qué sucede si la condición es falsa desde el principio:

int contador = 10;

// Bucle while
while (contador <= 5) {
    System.out.println("Este mensaje nunca se imprimirá");
    contador++;
}

// Bucle do-while
do {
    System.out.println("Este mensaje se imprimirá una vez");
    contador++;
} while (contador <= 5);

En este caso, el bucle while no se ejecuta ni una sola vez porque la condición es falsa desde el principio. Sin embargo, el bucle do-while se ejecuta una vez antes de evaluar la condición.

Casos de uso para while

El bucle while es especialmente útil en situaciones donde:

  • No se conoce el número exacto de iteraciones de antemano
  • La iteración depende de una condición externa o de entrada del usuario
  • Se necesita procesar datos hasta encontrar un valor específico
// Leer entrada del usuario hasta que ingrese "salir"
Scanner scanner = new Scanner(System.in);
String entrada = "";

while (!entrada.equalsIgnoreCase("salir")) {
    System.out.print("Ingrese un comando (o 'salir' para terminar): ");
    entrada = scanner.nextLine();
    
    if (!entrada.equalsIgnoreCase("salir")) {
        System.out.println("Procesando: " + entrada);
    }
}

System.out.println("Programa terminado");

Casos de uso para do-while

El bucle do-while es ideal cuando:

  • Se necesita ejecutar el código al menos una vez, independientemente de la condición
  • Se válida la entrada del usuario después de solicitarla
  • Se implementan menús de opciones que deben mostrarse al menos una vez
// Menú de opciones
Scanner scanner = new Scanner(System.in);
int opción;

do {
    System.out.println("\n--- MENÚ PRINCIPAL ---");
    System.out.println("1. Ver datos");
    System.out.println("2. Agregar nuevo registro");
    System.out.println("3. Modificar registro");
    System.out.println("4. Eliminar registro");
    System.out.println("0. Salir");
    System.out.print("Seleccione una opción: ");
    
    opción = scanner.nextInt();
    
    switch (opción) {
        case 1 -> System.out.println("Mostrando datos...");
        case 2 -> System.out.println("Agregando nuevo registro...");
        case 3 -> System.out.println("Modificando registro...");
        case 4 -> System.out.println("Eliminando registro...");
        case 0 -> System.out.println("Saliendo del programa...");
        default -> System.out.println("Opción no válida, intente de nuevo");
    }
} while (opción != 0);

Control de flujo dentro de bucles while y do-while

Al igual que en el bucle for, se pueden utilizar las instrucciones break y continue para controlar el flujo de ejecución:

int i = 1;

while (i <= 10) {
    if (i == 5) {
        System.out.println("Saltando el número 5");
        i++;
        continue; // Salta a la siguiente iteración
    }
    
    if (i == 8) {
        System.out.println("Encontrado el número 8, saliendo del bucle");
        break; // Sale del bucle
    }
    
    System.out.println("Número: " + i);
    i++;
}

Bucles anidados

También se pueden anidar bucles while y do-while, al igual que los bucles for:

int i = 1;

while (i <= 3) {
    int j = 1;
    while (j <= 3) {
        System.out.print("(" + i + "," + j + ") ");
        j++;
    }
    System.out.println(); // Nueva línea después de cada fila
    i++;
}

Salida:

(1,1) (1,2) (1,3) 
(2,1) (2,2) (2,3) 
(3,1) (3,2) (3,3) 

Comparación entre while, do-while y for

Cada tipo de bucle tiene sus propias ventajas y casos de uso ideales:

Bucle for: Ideal cuando se conoce el número de iteraciones de antemano.

Bucle while: Mejor cuando la condición de terminación depende de factores que pueden cambiar durante la ejecución.

Bucle do-while: Preferible cuando el bloque debe ejecutarse al menos una vez antes de evaluar la condición.

Ejemplos prácticos

Validación de entrada con do-while

Scanner scanner = new Scanner(System.in);
int número;

do {
    System.out.print("Ingrese un número positivo: ");
    número = scanner.nextInt();
    
    if (número <= 0) {
        System.out.println("Error: El número debe ser positivo");
    }
} while (número <= 0);

System.out.println("Número válido ingresado: " + número);

Búsqueda en una lista con while

List<String> nombres = List.of("Ana", "Carlos", "Elena", "David", "Beatriz");
String buscar = "Elena";
boolean encontrado = false;
int índice = 0;

while (índice < nombres.size() && !encontrado) {
    if (nombres.get(índice).equals(buscar)) {
        encontrado = true;
    } else {
        índice++;
    }
}

if (encontrado) {
    System.out.println("Nombre encontrado en la posición: " + índice);
} else {
    System.out.println("Nombre no encontrado");
}

Algoritmo de adivinanza con while

Scanner scanner = new Scanner(System.in);
Random random = new Random();
int númeroSecreto = random.nextInt(100) + 1; // Número entre 1 y 100
int intento;
int intentos = 0;
boolean adivinado = false;

System.out.println("Adivina el número entre 1 y 100");

while (!adivinado) {
    System.out.print("Ingresa tu intento: ");
    intento = scanner.nextInt();
    intentos++;
    
    if (intento < númeroSecreto) {
        System.out.println("El número es mayor");
    } else if (intento > númeroSecreto) {
        System.out.println("El número es menor");
    } else {
        adivinado = true;
        System.out.println("¡Correcto! Has adivinado en " + intentos + " intentos");
    }
}

Buenas prácticas

  • Evitar bucles infinitos: Asegurarse de que la condición eventualmente se vuelva falsa.
  • Inicialización adecuada: Inicializar las variables antes de usarlas en la condición del bucle.
  • Actualización clara: Actualizar las variables de control de manera clara y consistente.
  • Condiciones simples: Mantener las condiciones del bucle lo más simples posible.
  • Elegir el bucle adecuado: Utilizar for cuando se conoce el número de iteraciones, while cuando depende de una condición, y do-while cuando el bloque debe ejecutarse al menos una vez.
// Mal ejemplo: Posible bucle infinito
int contador = 0;
while (contador < 10) {
    System.out.println(contador);
    // Se olvidó incrementar contador
}

// Buen ejemplo
int contador = 0;
while (contador < 10) {
    System.out.println(contador);
    contador++; // Asegura que el bucle terminará
}

Consideraciones de rendimiento

  • Los bucles while y do-while pueden ser ligeramente más eficientes que el bucle for cuando la condición de terminación es simple y no requiere inicialización o actualización adicional.
  • Sin embargo, la diferencia de rendimiento suele ser insignificante en la mayoría de los casos, por lo que la elección del tipo de bucle debe basarse principalmente en la claridad y la adecuación al problema.
// Comparación de rendimiento (diferencia mínima)
long inicio, fin;

// Bucle for
inicio = System.nanoTime();
for (int i = 0; i < 1000000; i++) {
    // Operación
}
fin = System.nanoTime();
System.out.println("Tiempo con for: " + (fin - inicio) + " ns");

// Bucle while
inicio = System.nanoTime();
int j = 0;
while (j < 1000000) {
    // Misma operación
    j++;
}
fin = System.nanoTime();
System.out.println("Tiempo con while: " + (fin - inicio) + " ns");
Alan Sastre - Autor del tutorial

Alan Sastre

Ingeniero de Software y formador, CEO en CertiDevs

Ingeniero de software especializado en Full Stack y en Inteligencia Artificial. Como CEO de CertiDevs, Java es una de sus áreas de expertise. Con más de 15 años programando, 6K seguidores en LinkedIn y experiencia como formador, Alan se dedica a crear contenido educativo de calidad para desarrolladores de todos los niveles.

Más tutoriales de Java

Explora más contenido relacionado con Java y continúa aprendiendo con nuestros tutoriales gratuitos.

Aprendizajes de esta lección

Usar el bucle for en sus distintas variantes (clásico, múltiples variables, omisión de partes). Iterar colecciones y arrays con el bucle for-each. Aplicar while cuando el número de iteraciones no se conoce de antemano. Usar do-while para garantizar al menos una ejecución del bloque. Controlar el flujo dentro de bucles con break, continue y etiquetas. Elegir el tipo de bucle adecuado según el problema.

Cursos que incluyen esta lección

Esta lección forma parte de los siguientes cursos estructurados con rutas de aprendizaje