bucles en Java for foreach while do-while break continue guía

 Bucles en Java — for, for each y while comparados con Python

Los bucles en Java son el tema donde más diferencias hay respecto a Python en la sintaxis, y donde más similitudes hay respecto a C. Si vienes de Python el for de Java te va a parecer raro al principio porque no existe el range(). Si has visto bucles en C en IC2 el for de Java va a resultarte inmediatamente familiar.

En este artículo vemos los cuatro tipos de bucles, cuándo usar cada uno y cómo recorrer Strings carácter a carácter, algo que en Python era trivial y en Java requiere conocer un par de métodos.

El for con índice — la estructura de tres partes

En Python el for siempre recorre una colección, una lista, un rango, una cadena. No hay forma de escribir un for sin tener algo que recorrer. En Java el for clásico es diferente, es un bucle de control numérico con tres partes separadas por punto y coma:

for (inicialización; condición; actualización) {
    cuerpo
}
# Python — for con range
for i in range(5):
    print(i)    # → 0, 1, 2, 3, 4
// Java — for con las tres partes
for (int i = 0; i < 5; i++) {
    System.out.println(i);    // → 0, 1, 2, 3, 4
}

Las tres partes del for de Java:

int i = 0 — inicialización. Se ejecuta una sola vez al principio. Aquí se declara y se inicializa la variable del bucle.

i < 5 — condición. Se evalúa antes de cada iteración. Si es verdadera el cuerpo se ejecuta. Si es falsa el bucle termina.

i++ — actualización. Se ejecuta después de cada iteración. Aquí se avanza la variable del bucle.

El flujo exacto:

1. int i = 0          → inicialización (solo una vez)
2. ¿i < 5?  → true   → ejecuta el cuerpo
3. i++                → i ahora vale 1
4. ¿i < 5?  → true   → ejecuta el cuerpo
5. i++                → i ahora vale 2
...
6. i++                → i ahora vale 5
7. ¿i < 5?  → false  → el bucle termina

El for con rango — equivalencias con Python

El range() de Python tiene tres formas. Aquí está cómo se escribe cada una en Java:

# Python range(fin)
for i in range(5):         # 0, 1, 2, 3, 4
    print(i)
// Java equivalente
for (int i = 0; i < 5; i++) {
    System.out.println(i);
}
# Python range(inicio, fin)
for i in range(2, 7):      # 2, 3, 4, 5, 6
    print(i)
// Java equivalente
for (int i = 2; i < 7; i++) {
    System.out.println(i);
}
# Python range(inicio, fin, paso)
for i in range(0, 10, 2):  # 0, 2, 4, 6, 8
    print(i)
// Java equivalente
for (int i = 0; i < 10; i += 2) {
    System.out.println(i);
}
# Python range inverso
for i in range(5, 0, -1):  # 5, 4, 3, 2, 1
    print(i)
// Java equivalente
for (int i = 5; i > 0; i--) {
    System.out.println(i);
}

La diferencia mental clave: en Python range(n) genera la secuencia automáticamente. En Java tú controlas manualmente el inicio, la condición de parada y el avance. Más verboso, pero más flexible.

i++, i–, i+=n — los operadores de incremento

En Java hay operadores de incremento y decremento que no existen en Python:

i++    // i = i + 1 (postincremento)
i--    // i = i - 1 (postdecremento)
++i    // i = i + 1 (preincremento)
--i    // i = i - 1 (predecremento)
i += 2 // i = i + 2
i -= 3 // i = i - 3
i *= 2 // i = i * 2
i /= 4 // i = i / 4
i %= 3 // i = i % 3

En los bucles i++ y ++i son equivalentes, la diferencia importa cuando los usas dentro de expresiones, que no es el caso habitual en un for. Usa siempre i++ en los bucles para mantener la convención.

Declaración de la variable de los bucles en Java

La variable declarada en el for solo existe dentro del bucle, no es accesible fuera:

for (int i = 0; i < 5; i++) {
    System.out.println(i);    // i existe aquí
}
System.out.println(i);        // error — i no existe fuera del bucle

Si necesitas la variable fuera, declárala antes:

int i;
for (i = 0; i < 5; i++) {
    System.out.println(i);
}
System.out.println("Último valor: " + i);    // → 5

El for each — cuando no necesitas el índice

El for each de Java es el equivalente del for de Python sobre colecciones, recorre cada elemento sin necesitar el índice:

# Python — for sobre lista
numeros = [10, 20, 30, 40, 50]
for numero in numeros:
    print(numero)
// Java — for each sobre array
int[] numeros = {10, 20, 30, 40, 50};
for (int numero : numeros) {
    System.out.println(numero);
}

La sintaxis es for (tipo variable : colección), el : se lee «para cada… en…».

El for each funciona con arrays y con colecciones como ArrayList. No funciona si necesitas el índice, modificar elementos o recorrer hacia atrás, para eso usa el for con índice.

// for each — cuando solo quieres leer
int[] notas = {7, 8, 6, 9, 5};
int suma = 0;
for (int nota : notas) {
    suma += nota;
}
System.out.println("Media: " + (double) suma / notas.length);

// for con índice — cuando necesitas la posición
for (int i = 0; i < notas.length; i++) {
    System.out.println("Nota " + (i+1) + ": " + notas[i]);
}

Cuándo usar for con índice vs for each

for con índice → necesitas i, modificas elementos, recorres hacia atrás
for each       → solo lees elementos, no necesitas la posición

El while — cuando no sabes cuántas iteraciones habrá

El while en Java es idéntico al de Python evalúa la condición antes de cada iteración:

# Python
contador = 0
while contador < 5:
    print(contador)
    contador += 1
// Java
int contador = 0;
while (contador < 5) {
    System.out.println(contador);
    contador++;
}

El while es el bucle natural cuando no sabes de antemano cuántas iteraciones habrá, por ejemplo, leer datos hasta que el usuario escriba un valor de salida:

Scanner sc = new Scanner(System.in);
int suma = 0;
int numero = 0;

System.out.println("Introduce números (0 para terminar):");
while (numero != 0 || suma == 0) {    // continúa mientras no se introduzca 0
    numero = sc.nextInt();
    if (numero != 0) {
        suma += numero;
    }
}
System.out.println("Suma: " + suma);

Un patrón más limpio para bucles de entrada con centinela:

Scanner sc = new Scanner(System.in);
int suma = 0;

System.out.println("Introduce números (0 para terminar):");
while (true) {
    int numero = sc.nextInt();
    if (numero == 0) break;    // condición de salida
    suma += numero;
}
System.out.println("Suma: " + suma);

El do-while — ejecutar al menos una vez

El do-while no existe en Python. Es como el while pero evalúa la condición al final, esto garantiza que el cuerpo se ejecute al menos una vez aunque la condición sea falsa desde el principio:

// while — puede no ejecutarse nunca si la condición es falsa al inicio
while (condicion) {
    // puede que nunca se ejecute
}

// do-while — se ejecuta al menos una vez siempre
do {
    // se ejecuta al menos una vez
} while (condicion);

El do-while tiene un punto y coma al final, es la única estructura de control de Java que lo lleva.

El caso de uso más común es validar la entrada del usuario, pides el dato y luego compruebas si es válido:

Scanner sc = new Scanner(System.in);
int opcion;

do {
    System.out.println("Menú:");
    System.out.println("1. Opción A");
    System.out.println("2. Opción B");
    System.out.println("3. Salir");
    System.out.print("Elige (1-3): ");
    opcion = sc.nextInt();

    if (opcion < 1 || opcion > 3) {
        System.out.println("Opción inválida, elige entre 1 y 3\n");
    }
} while (opcion < 1 || opcion > 3);    // repite mientras la opción sea inválida

System.out.println("Elegiste la opción: " + opcion);

Si usaras while necesitarías inicializar opcion a un valor falso antes del bucle para que entrara, con do-while simplemente ejecutas una vez y luego compruebas.

Break y continue

break y continue funcionan igual que en Python y en C:

break — sale del bucle inmediatamente, sin terminar la iteración actual:

// Buscar el primer número par
int[] numeros = {3, 7, 8, 12, 5};
int primero_par = -1;

for (int n : numeros) {
    if (n % 2 == 0) {
        primero_par = n;
        break;    // para en cuanto encuentra el primero
    }
}
System.out.println("Primer par: " + primero_par);    // → 8

continue — salta al siguiente ciclo sin terminar la iteración actual:

// Imprimir solo los impares
for (int i = 0; i < 10; i++) {
    if (i % 2 == 0) continue;    // salta los pares
    System.out.print(i + " ");
}
// → 1 3 5 7 9

Con while se comportan igual:

int i = 0;
while (i < 10) {
    i++;
    if (i % 2 == 0) continue;
    System.out.print(i + " ");
}
// → 1 3 5 7 9

Cómo recorrer un String carácter a carácter

En Python recorrer un String era trivial, el for lo trata como una secuencia de caracteres directamente:

# Python
texto = "Hola"
for c in texto:
    print(c)    # H, o, l, a

En Java un String no es directamente iterable con for each. Hay dos formas de recorrerlo:

Forma 1 — con charAt() y el índice:

String texto = "Hola";
for (int i = 0; i < texto.length(); i++) {
    char c = texto.charAt(i);    // charAt(i) devuelve el char en posición i
    System.out.println(c);
}
// → H, o, l, a

charAt(i) devuelve el carácter en la posición i. length() devuelve la longitud del String, con paréntesis, a diferencia de los arrays que usan .length sin paréntesis.

String s = "Hola";
int[] arr = {1, 2, 3};

s.length()      // String — método, con paréntesis
arr.length      // array — atributo, sin paréntesis

Forma 2 — con toCharArray() y for each:

String texto = "Hola";
for (char c : texto.toCharArray()) {
    System.out.println(c);
}
// → H, o, l, a

toCharArray() convierte el String en un array de chars, que sí es iterable con for each.

Las dos formas son equivalentes. La primera con charAt es más común cuando necesitas el índice. La segunda con toCharArray es más limpia cuando solo necesitas los caracteres.

// Contar vocales en un String
String texto = "Hola Mundo";
int vocales = 0;

for (char c : texto.toLowerCase().toCharArray()) {
    if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u') {
        vocales++;
    }
}
System.out.println("Vocales: " + vocales);    // → 4

Bucles anidados — cómo no perderse

Los bucles anidados en Java funcionan igual que en Python y C, un bucle dentro de otro. La clave para no perderse es usar nombres de variables descriptivos y entender que el bucle interior se ejecuta completo por cada iteración del exterior:

// Tabla de multiplicar
for (int i = 1; i <= 10; i++) {          // bucle exterior — filas
    for (int j = 1; j <= 10; j++) {      // bucle interior — columnas
        System.out.printf("%4d", i * j);
    }
    System.out.println();    // salto de línea al terminar cada fila
}
   1   2   3   4   5   6   7   8   9  10
   2   4   6   8  10  12  14  16  18  20
   ...

El flujo: para i=1, j va de 1 a 10 completo. Luego i=2, j vuelve a ir de 1 a 10 completo. Y así sucesivamente.

La regla para no perderse: usa variables distintas en cada nivel, i para el exterior, j para el primero anidado, k para el segundo. Si reutilizas la misma variable en dos niveles el compilador da error porque la del interior oculta a la del exterior:

for (int i = 0; i < 3; i++) {
    for (int i = 0; i < 3; i++) {    // error — i ya existe en el ámbito exterior
        ...
    }
}

break en bucles anidados solo sale del bucle más interno:

// Buscar en una matriz 3x3
int[][] matriz = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
int buscado = 5;
boolean encontrado = false;

for (int i = 0; i < 3; i++) {
    for (int j = 0; j < 3; j++) {
        if (matriz[i][j] == buscado) {
            System.out.println("Encontrado en [" + i + "][" + j + "]");
            encontrado = true;
            break;    // solo sale del bucle interior
        }
    }
    if (encontrado) break;    // sale del bucle exterior
}

Un programa completo con todos los bucles

import java.util.Scanner;

public class BuclesDemo {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        // FOR con índice — tabla de cuadrados
        System.out.println("=== Tabla de cuadrados ===");
        for (int i = 1; i <= 10; i++) {
            System.out.printf("%2d² = %3d%n", i, i * i);
        }

        // FOR EACH — suma de elementos
        System.out.println("\n=== Suma de notas ===");
        double[] notas = {7.5, 8.0, 6.5, 9.0, 5.5};
        double suma = 0;
        for (double nota : notas) {
            suma += nota;
        }
        System.out.printf("Media: %.2f%n", suma / notas.length);

        // WHILE — adivina el número
        System.out.println("\n=== Adivina el número (1-10) ===");
        int secreto = 7;
        int intentos = 0;
        int intento;
        while (true) {
            System.out.print("Tu intento: ");
            intento = sc.nextInt();
            intentos++;
            if (intento == secreto) {
                System.out.println("¡Correcto en " + intentos + " intentos!");
                break;
            } else if (intento < secreto) {
                System.out.println("Más alto");
            } else {
                System.out.println("Más bajo");
            }
        }

        // DO-WHILE — menú con validación
        System.out.println("\n=== Menú ===");
        int opcion;
        do {
            System.out.println("1. Saludar  2. Despedir  3. Salir");
            System.out.print("Opción: ");
            opcion = sc.nextInt();
            switch (opcion) {
                case 1: System.out.println("¡Hola!"); break;
                case 2: System.out.println("¡Adiós!"); break;
                case 3: System.out.println("Saliendo..."); break;
                default: System.out.println("Opción inválida");
            }
        } while (opcion != 3);

        // RECORRER STRING
        System.out.println("\n=== Análisis de texto ===");
        String texto = "Java FP2 2025";
        int letras = 0, espacios = 0, numeros = 0;
        for (char c : texto.toCharArray()) {
            if (Character.isLetter(c)) letras++;
            else if (Character.isDigit(c)) numeros++;
            else if (c == ' ') espacios++;
        }
        System.out.printf("Texto: \"%s\"%n", texto);
        System.out.printf("Letras: %d | Números: %d | Espacios: %d%n",
                          letras, numeros, espacios);

        sc.close();
    }
}

Fíjate en Character.isLetter(c) y Character.isDigit(c) ,la clase Character tiene métodos útiles para clasificar chars. No necesitas importarla, viene incluida en Java.

Resumen rápido

// FOR CON ÍNDICE
for (int i = 0; i < n; i++) { }    // i de 0 a n-1
for (int i = 1; i <= n; i++) { }   // i de 1 a n
for (int i = n; i > 0; i--) { }    // i de n a 1
for (int i = 0; i < n; i += 2) { } // i de 2 en 2

// EQUIVALENCIAS CON PYTHON range()
// range(n)        → for (int i = 0; i < n; i++)
// range(a, b)     → for (int i = a; i < b; i++)
// range(a, b, p)  → for (int i = a; i < b; i += p)
// range(n, 0, -1) → for (int i = n; i > 0; i--)

// OPERADORES DE INCREMENTO
i++   // i += 1
i--   // i -= 1
i += n  i -= n  i *= n  i /= n  i %= n

// FOR EACH
for (tipo elemento : coleccion) { }
// solo lectura, sin índice
// funciona con arrays y colecciones

// FOR con índice vs FOR EACH
// índice  → necesitas i, modificas, recorres hacia atrás
// each    → solo lees, no necesitas posición

// WHILE
while (condicion) { }
// evalúa antes — puede no ejecutarse nunca

// DO-WHILE
do {
    ...
} while (condicion);    // ← punto y coma obligatorio
// evalúa después — se ejecuta al menos una vez

// BREAK Y CONTINUE
break;      // sale del bucle inmediatamente
continue;   // salta al siguiente ciclo

// RECORRER STRING
// Forma 1 — con índice
for (int i = 0; i < s.length(); i++) {
    char c = s.charAt(i);
}
// Forma 2 — for each
for (char c : s.toCharArray()) { }

// String.length() — con paréntesis (es un método)
// array.length    — sin paréntesis (es un atributo)

// BUCLES ANIDADOS
for (int i = ...) {         // exterior
    for (int j = ...) {     // interior — usa variable distinta
        ...
    }
}
// break solo sale del bucle más interno

// CLASE CHARACTER
Character.isLetter(c)   // ¿es letra?
Character.isDigit(c)    // ¿es dígito?
Character.isWhitespace(c) // ¿es espacio?
Character.toUpperCase(c)  // a mayúscula
Character.toLowerCase(c)  // a minúscula

En el próximo artículo vemos los métodos estáticos en Java, cómo crear funciones propias, el paso de parámetros y la diferencia con Python.


Java loops — for, for each, while and do-while from scratch

Java loops are where the syntax differences from Python are most visible, and where the similarities with C are strongest. If you know Python, Java’s for will feel unusual at first because there’s no range(). If you’ve seen C loops in IC2, Java’s for will feel immediately familiar.

The for loop — three parts structure

In Python for always iterates over a collection. In Java the classic for is a numeric control loop with three semicolon-separated parts:

for (initialisation; condition; update) {
    body
}
# Python
for i in range(5):
    print(i)    # 0, 1, 2, 3, 4
// Java
for (int i = 0; i < 5; i++) {
    System.out.println(i);    // 0, 1, 2, 3, 4
}

int i = 0, runs once at the start. i < 5, checked before each iteration. False → loop ends. i++, runs after each iteration.

Range equivalents

range(n)         → for (int i = 0; i < n; i++)
range(a, b)      → for (int i = a; i < b; i++)
range(a, b, step)→ for (int i = a; i < b; i += step)
range(n, 0, -1)  → for (int i = n; i > 0; i--)

Increment operators

i++    // i += 1    i--   // i -= 1
i += 2  i -= 3  i *= 2  i /= 4  i %= 3

The loop variable only exists inside the loop, not accessible outside unless declared before.

For each, when you don’t need the index

# Python
numbers = [10, 20, 30]
for n in numbers:
    print(n)
// Java
int[] numbers = {10, 20, 30};
for (int n : numbers) {
    System.out.println(n);
}

Syntax: for (type variable : collection), the : reads «for each… in…»

Use for with index: need i, modify elements, iterate backwards
Use for each:       only reading, don't need position

while — when you don’t know the iteration count

# Python
counter = 0
while counter < 5:
    print(counter)
    counter += 1
// Java
int counter = 0;
while (counter < 5) {
    System.out.println(counter);
    counter++;
}

Common pattern, read until sentinel value:

while (true) {
    int number = sc.nextInt();
    if (number == 0) break;
    sum += number;
}

do-while — execute at least once

Not in Python. Evaluates condition at the end, body always runs at least once:

do {
    System.out.println("Menu:");
    System.out.print("Option (1-3): ");
    option = sc.nextInt();
    if (option < 1 || option > 3)
        System.out.println("Invalid");
} while (option < 1 || option > 3);    // semicolon required

Note the semicolon after while(condition), the only control structure in Java that ends with one.

break and continue

// break — exit loop immediately
for (int n : numbers) {
    if (n % 2 == 0) {
        first_even = n;
        break;
    }
}

// continue — skip to next iteration
for (int i = 0; i < 10; i++) {
    if (i % 2 == 0) continue;    // skip evens
    System.out.print(i + " ");
}
// → 1 3 5 7 9

Traversing a String character by character

# Python — trivial
for c in "Hello":
    print(c)
// Java — two ways

// Form 1 — charAt with index
String text = "Hello";
for (int i = 0; i < text.length(); i++) {
    char c = text.charAt(i);
    System.out.println(c);
}

// Form 2 — toCharArray with for each
for (char c : text.toCharArray()) {
    System.out.println(c);
}

Important: String.length() uses parentheses (it’s a method). array.length uses no parentheses (it’s an attribute).

Nested loops

// Multiplication table
for (int i = 1; i <= 10; i++) {          // outer — rows
    for (int j = 1; j <= 10; j++) {      // inner — columns
        System.out.printf("%4d", i * j);
    }
    System.out.println();
}

Always use different variable names at each level, i, j, k. break only exits the innermost loop, add a boolean flag or check to also break the outer loop.

Character class

Character.isLetter(c)      // is it a letter?
Character.isDigit(c)       // is it a digit?
Character.isWhitespace(c)  // is it whitespace?
Character.toUpperCase(c)   // to uppercase
Character.toLowerCase(c)   // to lowercase

Quick summary

// FOR WITH INDEX
for (int i = 0; i < n; i++) { }
for (int i = n; i > 0; i--) { }
for (int i = 0; i < n; i += 2) { }

// RANGE EQUIVALENTS
// range(n)      → for (int i = 0; i < n; i++)
// range(a,b)    → for (int i = a; i < b; i++)
// range(a,b,s)  → for (int i = a; i < b; i += s)

// FOR EACH
for (type element : collection) { }

// WHILE
while (condition) { }    // may never run

// DO-WHILE
do { } while (condition);    // semicolon required — runs at least once

// BREAK AND CONTINUE
break;      // exit loop
continue;   // skip to next iteration

// STRING TRAVERSAL
for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); }
for (char c : s.toCharArray()) { }

// length() vs length
s.length()    // String — method, parentheses
arr.length    // array — attribute, no parentheses

// NESTED LOOPS
// Use i, j, k for each level
// break only exits innermost loop

Publicaciones Similares

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *