Bucle for-each (for mejorado) en Java
Recorre arrays y colecciones en Java con el bucle for-each mejorado para una iteración más simple y segura.
Java 5 introdujo el bucle for mejorado — comúnmente llamado bucle for-each — para recorrer cada elemento de un array o colección sin necesidad de gestionar un índice manualmente. Cuando no necesitas el índice, casi siempre es la opción más limpia.
Sintaxis
for (Type element : iterable) {
// body — runs once per element
}Léelo como: para cada element en iterable. Los dos puntos son obligatorios; no son lo mismo que los punto y coma del bucle for regular.
int[] nums = {10, 20, 30, 40};
for (int n : nums) {
System.out.println(n);
}Imprime 10 20 30 40. Sin contador, sin nums.length, sin nums[i].
Funciona con arrays y cualquier Iterable
El bucle for-each acepta:
- Cualquier array.
- Cualquier cosa que implemente
java.lang.Iterable<T>— lo que incluye todaCollection(comoList,SetyQueue), además de muchos otros tipos del JDK y de bibliotecas.
import java.util.List;
List<String> names = List.of("alice", "bob", "carol");
for (String name : names) {
System.out.println(name);
}
String text = "abc";
for (char c : text.toCharArray()) {
System.out.println(c);
}Ten en cuenta que String en sí mismo no es iterable, pero text.toCharArray() produce un array, que sí lo es.
Un Map tampoco implementa Iterable directamente — en su lugar se itera una de sus vistas: map.keySet(), map.values() o map.entrySet(). Cada una devuelve un Set o Collection, que el bucle for-each puede manejar.
La variable de elemento es una copia
La variable en la cabecera del bucle recibe el valor de cada elemento. Para tipos primitivos, modificarla no cambia el array:
int[] nums = {1, 2, 3};
for (int n : nums) {
n *= 10; // doesn't touch nums
}
System.out.println(nums[0]); // still 1Para objetos, la variable contiene una referencia, por lo que llamar a métodos que mutan el objeto afectará al original. Sin embargo, reasignar la variable (name = "...";) solo cambia la copia local.
Si necesitas modificar los propios elementos, usa un bucle indexado:
for (int i = 0; i < nums.length; i++) {
nums[i] *= 10;
}Cuándo no puedes usar for-each
Un bucle for-each oculta el índice. Ese es su propósito — pero también significa que no puedes usarlo cuando necesitas:
- El índice (
"item " + i + ": " + value) - Eliminar elementos durante la iteración (usa un
Iteratorexplícito y llama aiterator.remove()) - Dos colecciones en paralelo (usa índices)
- Iterar en orden inverso o saltar elementos (usa un
forindexado)
No modifiques la colección mientras iteras
Un bucle for-each sobre una colección usa un Iterator internamente. Si cambias la estructura de la colección durante la iteración (añadir o eliminar elementos), el iterador detecta la discrepancia en el siguiente paso y lanza una ConcurrentModificationException:
List<String> names = new ArrayList<>(List.of("alice", "bob"));
for (String n : names) {
names.remove(n); // ConcurrentModificationException
}Para eliminar de forma segura, controla el bucle con un Iterator explícito y llama a su remove() — mantiene el iterador y la lista sincronizados:
Iterator<String> it = names.iterator();
while (it.hasNext()) {
String n = it.next();
if (n.startsWith("a")) {
it.remove(); // safe
}
}En Java 8+ a menudo puedes omitir el bucle por completo: names.removeIf(n -> n.startsWith("a"));.
Leer o reemplazar un elemento (list.set(i, x)) durante un bucle for-each está bien. Solo los cambios estructurales — add y remove en la propia colección — desencadenan la excepción.
Un ejemplo completo
Qué viene después
Cuando necesitas salir de un bucle antes de tiempo — o saltar el resto de la iteración actual — usa break y continue.