W3docs

Ciclo for-each (Enhanced for) in Java

Itera su array e collezioni in Java con il ciclo for-each per un'iterazione più semplice e sicura.

Java 5 ha introdotto il ciclo for avanzato — comunemente chiamato ciclo for-each — per scorrere ogni elemento di un array o di una collezione senza dover gestire manualmente un indice. Quando non hai bisogno dell'indice, è quasi sempre la scelta più pulita.

Sintassi

for (Type element : iterable) {
  // body — runs once per element
}

Si legge come: per ogni element in iterable. I due punti sono obbligatori; non è la stessa cosa dei punti e virgola del ciclo for normale.

int[] nums = {10, 20, 30, 40};

for (int n : nums) {
  System.out.println(n);
}

Stampa 10 20 30 40. Nessun contatore, nessun nums.length, nessun nums[i].

Funziona su array e qualsiasi Iterable

Il ciclo for-each accetta:

  • Qualsiasi array.
  • Qualsiasi cosa che implementi java.lang.Iterable<T> — il che significa ogni Collection (come List, Set e Queue), oltre a molti altri tipi JDK e di libreria.
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);
}

Nota che String in sé non è iterabile, ma text.toCharArray() produce un array, che lo è.

Una Map non è nemmeno direttamente Iterable — si itera su una delle sue viste: map.keySet(), map.values() o map.entrySet(). Ognuna di esse restituisce un Set o una Collection, che il ciclo for-each gestisce.

La variabile elemento è una copia

La variabile nell'intestazione del ciclo riceve il valore di ogni elemento. Per i tipi primitivi, modificarla non cambia l'array:

int[] nums = {1, 2, 3};
for (int n : nums) {
  n *= 10;          // doesn't touch nums
}
System.out.println(nums[0]);   // still 1

Per gli oggetti, la variabile contiene un riferimento, quindi chiamare metodi che mutano l'oggetto influirà sull'originale. Ma riassegnare la variabile (name = "...";) cambia solo la copia locale.

Se hai bisogno di modificare gli elementi stessi, usa un ciclo con indice:

for (int i = 0; i < nums.length; i++) {
  nums[i] *= 10;
}

Quando non puoi usare for-each

Un ciclo for-each nasconde l'indice. Questo è il punto — ma significa anche che non puoi usarlo quando hai bisogno di:

  • L'indice ("item " + i + ": " + value)
  • Rimuovere elementi durante l'iterazione (usa un Iterator esplicito e chiama iterator.remove())
  • Due collezioni in parallelo (usa gli indici)
  • Iterare in ordine inverso o saltare elementi (usa un for con indice)

Non modificare la collezione durante l'iterazione

Un ciclo for-each su una collezione usa internamente un Iterator. Se modifichi la struttura della collezione durante l'iterazione (aggiungi o rimuovi elementi), l'iteratore si accorge della discrepanza al passo successivo e lancia una ConcurrentModificationException:

List<String> names = new ArrayList<>(List.of("alice", "bob"));
for (String n : names) {
  names.remove(n);   // ConcurrentModificationException
}

Per rimuovere in modo sicuro, guida il ciclo con un Iterator esplicito e chiama il suo remove() — mantiene l'iteratore e la lista sincronizzati:

Iterator<String> it = names.iterator();
while (it.hasNext()) {
  String n = it.next();
  if (n.startsWith("a")) {
    it.remove();      // safe
  }
}

Con Java 8+ puoi spesso saltare del tutto il ciclo: names.removeIf(n -> n.startsWith("a"));.

Attenzione

Leggere o sostituire un elemento (list.set(i, x)) durante un ciclo for-each va bene. Sono solo le modifiche strutturali — add e remove sulla collezione stessa — a generare l'eccezione.

Un esempio pratico

java— editable, runs on the server

Cosa viene dopo

Quando hai bisogno di uscire da un ciclo anticipatamente — o di saltare il resto dell'iterazione corrente — usa break e continue.

Pratica

Pratica
In un ciclo for-each su un int[], modificare la variabile del ciclo nel corpo...
In un ciclo for-each su un int[], modificare la variabile del ciclo nel corpo...
Was this page helpful?