Loop Annidati in Java
Combina loop dentro altri loop in Java per elaborare dati multidimensionali, con pattern per matrici e griglie.
Un loop annidato è un loop all'interno di un altro loop. Il loop interno viene eseguito completamente ad ogni iterazione del loop esterno, quindi il corpo viene eseguito esterno × interno volte. Questa è la struttura di base per ogni problema che coinvolge righe e colonne, coppie o dati multidimensionali.
Questo capitolo presuppone che tu conosca le forme base dei loop — il loop for e il loop while. Qualsiasi loop può essere annidato all'interno di un altro; gli esempi seguenti usano for perché è il più comune, ma la regola è la stessa per while e for-each.
Due loop for
for (int i = 1; i <= 3; i++) {
for (int j = 1; j <= 3; j++) {
System.out.println(i + "," + j);
}
}Output:
1,1
1,2
1,3
2,1
2,2
2,3
3,1
3,2
3,3Per ogni valore di i, il loop interno percorre j da 1 a 3 prima che i avanzi. Nota che j viene reinizializzato a 1 ad ogni iterazione esterna — il loop interno riparte da capo ogni volta che il loop esterno si ripete. Mantieni distinte le variabili dei loop (i e j in questo caso); riutilizzare lo stesso nome in entrambi i loop è una fonte comune di bug.
Scorrere un array 2D
L'uso classico dei loop annidati è l'iterazione su una matrice:
int[][] grid = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
for (int r = 0; r < grid.length; r++) {
for (int c = 0; c < grid[r].length; c++) {
System.out.print(grid[r][c] + " ");
}
System.out.println();
}Ogni riga della griglia è a sua volta un array; il loop esterno itera le righe, il loop interno itera le celle di ciascuna riga. La forma for-each è ancora più pulita quando non hai bisogno degli indici:
for (int[] row : grid) {
for (int cell : row) {
System.out.print(cell + " ");
}
System.out.println();
}Stampare pattern
I loop annidati sono un esercizio classico per stampare pattern. Un triangolo di asterischi:
int rows = 5;
for (int i = 1; i <= rows; i++) {
for (int j = 1; j <= i; j++) {
System.out.print("*");
}
System.out.println();
}Output:
*
**
***
****
*****Il conteggio del loop interno dipende dalla variabile del loop esterno — un pattern potente che ricorre costantemente.
Attenzione alla complessità
Un singolo loop su n elementi viene eseguito n volte. Un loop annidato al suo interno viene eseguito n × n = n² volte. Tre loop annidati vengono eseguiti n³ volte. Per n piccoli questo non ha importanza; per n grandi è molto rilevante:
| n | n² | n³ |
|---|---|---|
| 10 | 100 | 1,000 |
| 100 | 10,000 | 1,000,000 |
| 1,000 | 1,000,000 | 1,000,000,000 |
Se il tuo loop annidato opera su un insieme di dati grande, chiediti se hai davvero bisogno del loop interno. Una ricerca con HashMap spesso sostituisce un loop di ricerca interno e trasforma O(n²) in O(n).
break e continue influenzano solo il loop interno
Lo abbiamo visto in break e continue: senza un'etichetta, entrambi si applicano solo al loop più interno. Per uscire dal loop esterno o saltare la sua iterazione dall'interno di quello interno, usa un break o continue con etichetta — vedi istruzioni con etichetta.
Un esempio pratico
Cosa c'è dopo
Quando hai bisogno di usare break o continue su un loop esterno dall'interno di uno interno, le istruzioni con etichetta offrono un modo pulito per farlo.