Loops Aninhados em Java
Combine loops dentro de loops em Java para processar dados multidimensionais, com padrões para matrizes e grades.
Um loop aninhado é um loop dentro de outro loop. O loop interno executa até o fim a cada passagem do loop externo, portanto o corpo é executado externo × interno vezes. Este é o formato básico para todo problema envolvendo linhas e colunas, pares ou dados multidimensionais.
Este capítulo pressupõe que você conhece as formas básicas de loop — o loop for e o loop while. Qualquer loop pode ser aninhado dentro de outro; os exemplos abaixo usam for por ser o mais comum, mas a regra é a mesma para while e for-each.
Dois loops for
for (int i = 1; i <= 3; i++) {
for (int j = 1; j <= 3; j++) {
System.out.println(i + "," + j);
}
}Saída:
1,1
1,2
1,3
2,1
2,2
2,3
3,1
3,2
3,3Para cada valor de i, o loop interno percorre j de 1 a 3 antes que i avance. Note que j é reinicializado para 1 a cada passagem externa — o loop interno começa do zero sempre que o loop externo se repete. Mantenha as variáveis de loop distintas (i e j aqui); reutilizar o mesmo nome nos dois loops é uma fonte comum de bugs.
Percorrendo um array 2D
O uso clássico de loops aninhados é iterar sobre uma matriz:
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();
}Cada linha da grade é por si só um array; o loop externo itera pelas linhas, o loop interno itera pelas células de cada linha. A forma for-each é ainda mais limpa quando você não precisa dos índices:
for (int[] row : grid) {
for (int cell : row) {
System.out.print(cell + " ");
}
System.out.println();
}Imprimindo padrões
Loops aninhados são um exercício clássico para imprimir padrões. Um triângulo de estrelas:
int rows = 5;
for (int i = 1; i <= rows; i++) {
for (int j = 1; j <= i; j++) {
System.out.print("*");
}
System.out.println();
}Saída:
*
**
***
****
*****A contagem do loop interno depende da variável do loop externo — um padrão poderoso que aparece constantemente.
Atenção à complexidade
Um único loop sobre n itens executa n vezes. Um loop aninhado dentro dele executa n × n = n² vezes. Três loops aninhados executam n³ vezes. Para n pequeno isso não importa; para n grande importa muito:
| n | n² | n³ |
|---|---|---|
| 10 | 100 | 1,000 |
| 100 | 10,000 | 1,000,000 |
| 1,000 | 1,000,000 | 1,000,000,000 |
Se o seu loop aninhado percorre um grande conjunto de dados, pergunte-se se você realmente precisa do loop interno. Uma busca em HashMap frequentemente substitui um loop de busca interno e transforma O(n²) em O(n).
break e continue afetam apenas o loop interno
Vimos isso em break e continue: sem um rótulo, ambos se aplicam apenas ao loop mais interno. Para sair do loop externo ou pular sua iteração de dentro do loop interno, use um break ou continue rotulado — veja instruções rotuladas.
Um exemplo prático
O que vem a seguir
Quando você precisar usar break ou continue em um loop externo a partir de dentro de um loop interno, as instruções rotuladas oferecem uma forma limpa de fazer isso.