Java Laços Aninhados

O corpo de um laço pode ter qualquer instrução, inclusive outro laço. Isso se chama laços aninhados (como ninhos, um dentro do outro). É o jeito de trabalhar com coisas que têm duas dimensões: linhas e colunas, fileiras e cadeiras, dias e horários, a tabela de multiplicação inteira.

Você vai aprender
  • Como um laço dentro de outro funciona, volta por volta.
  • A regra que resolve quase todo exercício: o de fora são as linhas, o de dentro são as colunas.
  • Desenhar retângulos, triângulos e pirâmides com *.
  • Montar a tabela de multiplicação de 1 a 10.
  • Contar quantas vezes o corpo de dentro roda, e por que isso cresce rápido.
  • Os erros mais comuns: mesmo nome de variável, passo trocado, println no lugar de print.

Os exemplos rodam no terminal da Ana (máquina fictícia notebook, pasta ~/java, JDK 25) com java Main.java. Usamos o for em quase todos, mas a ideia vale para qualquer laço.


A ideia antes do código

Pense num relógio. O ponteiro das horas anda uma vez; enquanto isso, o ponteiro dos minutos dá uma volta inteira (60 passos). Só então as horas andam de novo, e os minutos começam outra volta completa.

Laços aninhados são exatamente isso:

  • O laço de fora é o ponteiro das horas: anda devagar.
  • O laço de dentro é o ponteiro dos minutos: a cada passo do de fora, ele recomeça do zero e vai até o fim.

Veja um relógio simplificado, de 15 em 15 minutos, por duas horas:

public class Main {
    public static void main(String[] args) {
        for (int h = 0; h <= 1; h++) {
            for (int m = 0; m < 60; m += 15) {
                System.out.println(h + "h" + m + "min");
            }
        }
    }
}
$ java Main.java
0h0min
0h15min
0h30min
0h45min
1h0min                       « o laço das horas andou; os minutos recomeçaram do 0
1h15min
1h30min
1h45min

Volta por volta

Para enxergar a ordem exata, vamos fazer cada laço "se apresentar". O de dentro tem um recuo de quatro espaços na mensagem, só para ficar visível:

public class Main {
    public static void main(String[] args) {
        for (int i = 1; i <= 2; i++) {
            System.out.println("Laço de fora: i = " + i);
            for (int j = 1; j <= 3; j++) {
                System.out.println("    laço de dentro: i = " + i + ", j = " + j);
            }
        }
        System.out.println("Fim");
    }
}
$ java Main.java
Laço de fora: i = 1
    laço de dentro: i = 1, j = 1
    laço de dentro: i = 1, j = 2
    laço de dentro: i = 1, j = 3
Laço de fora: i = 2
    laço de dentro: i = 2, j = 1     « o j recomeçou do 1
    laço de dentro: i = 2, j = 2
    laço de dentro: i = 2, j = 3
Fim

Três fatos para guardar:

  1. Para cada volta do de fora, o de dentro roda inteiro (aqui, 3 voltas).
  2. O j recomeça do 1 a cada volta do de fora. Isso acontece porque o int j = 1 está no cabeçalho do laço de dentro, e esse cabeçalho é executado de novo cada vez que o programa chega nele.
  3. O de dentro enxerga o i do de fora (ele aparece na mensagem), mas o de fora não enxerga o j: ele só existe dentro do laço de dentro (veja o escopo em for).

Linhas e colunas

O uso mais comum: o laço de fora escolhe a linha, o de dentro escreve as colunas dessa linha. A sala de cinema da cidade tem as fileiras A, B e C, com 4 cadeiras cada:

public class Main {
    public static void main(String[] args) {
        for (char fileira = 'A'; fileira <= 'C'; fileira++) {
            for (int cadeira = 1; cadeira <= 4; cadeira++) {
                System.out.print(fileira + "" + cadeira + " ");
            }
            System.out.println();
        }
    }
}
$ java Main.java
A1 A2 A3 A4
B1 B2 B3 B4
C1 C2 C3 C4
LinhaO que faz
for (char fileira = 'A'; fileira <= 'C'; fileira++)Laço de fora: uma volta por fileira (A, B, C). Um char pode contar, veja char e boolean.
for (int cadeira = 1; cadeira <= 4; cadeira++)Laço de dentro: uma volta por cadeira da fileira atual.
System.out.print(fileira + "" + cadeira + " ");print, sem "ln": escreve a cadeira e fica na mesma linha. O "" no meio força a junção como texto (sem ele, 'A' + 1 seria a soma do código da letra com 1; veja Concatenação).
System.out.println();Está no laço de fora, depois do de dentro: terminada a fileira, pula para a próxima linha.
A receita das figuras

Laço de fora = linhas. Laço de dentro = o que vai em cada linha, com print. Depois do laço de dentro, um println() para fechar a linha. Com essa receita você desenha qualquer figura dos exercícios clássicos.


Desenhando com *

Retângulo

3 linhas, 5 estrelas em cada:

public class Main {
    public static void main(String[] args) {
        for (int linha = 1; linha <= 3; linha++) {
            for (int coluna = 1; coluna <= 5; coluna++) {
                System.out.print("*");
            }
            System.out.println();
        }
    }
}
$ java Main.java
*****
*****
*****

Missão: desenhe um retângulo de 4 linhas com 6 símbolos # em cada. Mantenha os dois laços.

public class Main {
    public static void main(String[] args) {
        for (int linha = 1; linha <= 3; linha++) {
            for (int coluna = 1; coluna <= 5; coluna++) {
                System.out.print("*");
            }
            System.out.println();
        }
    }
}
public class Main {
    public static void main(String[] args) {
        for (int linha = 1; linha <= 4; linha++) {
            for (int coluna = 1; coluna <= 6; coluna++) {
                System.out.print("#");
            }
            System.out.println();
        }
    }
}

Triângulo

Agora a linha 1 tem 1 estrela, a linha 2 tem 2, e assim por diante. O truque é um só: o limite do laço de dentro deixa de ser um número fixo e passa a ser a variável do laço de fora:

public class Main {
    public static void main(String[] args) {
        for (int linha = 1; linha <= 5; linha++) {
            for (int coluna = 1; coluna <= linha; coluna++) {
                System.out.print("*");
            }
            System.out.println();
        }
    }
}
$ java Main.java
*
**
***
****
*****
linhaO de dentro vai de 1 até…Estrelas
11*
22**
33***
44****
55*****

Triângulo de cabeça para baixo

Basta o laço de fora contar para baixo, de 5 até 1. O de dentro continua igual:

public class Main {
    public static void main(String[] args) {
        for (int linha = 5; linha >= 1; linha--) {
            for (int coluna = 1; coluna <= linha; coluna++) {
                System.out.print("*");
            }
            System.out.println();
        }
    }
}
$ java Main.java
*****
****
***
**
*

Pirâmide

Uma pirâmide centralizada precisa de dois laços de dentro, um depois do outro: primeiro os espaços da esquerda, depois as estrelas. Na linha linha de uma pirâmide de altura 4, há 4 - linha espaços e 2 * linha - 1 estrelas (1, 3, 5, 7):

public class Main {
    public static void main(String[] args) {
        int altura = 4;
        for (int linha = 1; linha <= altura; linha++) {
            for (int espaco = 1; espaco <= altura - linha; espaco++) {
                System.out.print(" ");
            }
            for (int estrela = 1; estrela <= 2 * linha - 1; estrela++) {
                System.out.print("*");
            }
            System.out.println();
        }
    }
}
$ java Main.java
   *
  ***
 *****
*******

Os dois laços de dentro estão lado a lado, não um dentro do outro: a cada linha, primeiro roda o dos espaços inteiro, depois o das estrelas inteiro. Trocar altura por 10 desenha uma pirâmide maior sem mexer em mais nada.


A tabela de multiplicação

Na aula de for, um laço fez a tabuada de um número. Com dois laços, saem todas, de 1 a 10, numa tabela: a linha é o i, a coluna é o j, e cada célula é i * j. Para alinhar as colunas, cada número é seguido de um "\t", o caractere de tabulação (o Tab, veja Caracteres Especiais):

public class Main {
    public static void main(String[] args) {
        for (int i = 1; i <= 10; i++) {
            for (int j = 1; j <= 10; j++) {
                System.out.print(i * j + "\t");
            }
            System.out.println();
        }
    }
}
$ java Main.java
1	2	3	4	5	6	7	8	9	10
2	4	6	8	10	12	14	16	18	20
3	6	9	12	15	18	21	24	27	30
4	8	12	16	20	24	28	32	36	40
5	10	15	20	25	30	35	40	45	50
6	12	18	24	30	36	42	48	54	60
7	14	21	28	35	42	49	56	63	70
8	16	24	32	40	48	56	64	72	80
9	18	27	36	45	54	63	72	81	90
10	20	30	40	50	60	70	80	90	100	

Aqui i * j + "\t" funciona sem parênteses porque a multiplicação vem antes da soma (veja Precedência): primeiro i * j vira um número, depois ele é juntado com o "\t". Para alinhar com mais controle, existe o printf, que você verá em Formatar Texto.

Do jeito "livro": uma tabuada embaixo da outra

O laço de dentro não precisa escrever na mesma linha. Aqui, o de fora escreve um título e o de dentro escreve cinco linhas:

public class Main {
    public static void main(String[] args) {
        for (int n = 1; n <= 3; n++) {
            System.out.println("Tabuada do " + n + ":");
            for (int i = 1; i <= 5; i++) {
                System.out.println("  " + n + " x " + i + " = " + (n * i));
            }
        }
    }
}
$ java Main.java
Tabuada do 1:
  1 x 1 = 1
  1 x 2 = 2
  1 x 3 = 3
  1 x 4 = 4
  1 x 5 = 5
Tabuada do 2:
  2 x 1 = 2
  2 x 2 = 4
  2 x 3 = 6
  2 x 4 = 8
  2 x 5 = 10
Tabuada do 3:
  3 x 1 = 3
  3 x 2 = 6
  3 x 3 = 9
  3 x 4 = 12
  3 x 5 = 15

Contando as voltas

Quantas vezes o corpo de dentro roda? Vamos perguntar ao próprio programa, com um contador:

public class Main {
    public static void main(String[] args) {
        int voltas = 0;
        for (int i = 1; i <= 3; i++) {
            for (int j = 1; j <= 4; j++) {
                voltas++;
            }
        }
        System.out.println("O corpo de dentro rodou " + voltas + " vezes");
    }
}
$ java Main.java
O corpo de dentro rodou 12 vezes

3 voltas de fora × 4 de dentro = 12. A regra geral: quando os limites são fixos, multiplique. Foi assim que a tabela de multiplicação escreveu 10 × 10 = 100 números.

No triângulo, o de dentro roda cada vez mais. Comparando os dois formatos com n = 10:

public class Main {
    public static void main(String[] args) {
        int n = 10;
        int quadrado = 0;
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                quadrado++;
            }
        }
        int triangulo = 0;
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= i; j++) {
                triangulo++;
            }
        }
        System.out.println("n = " + n);
        System.out.println("Quadrado (j até n): " + quadrado + " voltas");
        System.out.println("Triângulo (j até i): " + triangulo + " voltas");
    }
}
$ java Main.java
n = 10
Quadrado (j até n): 100 voltas
Triângulo (j até i): 55 voltas      « 1 + 2 + 3 + ... + 10
Por que contar importa

Laços aninhados crescem rápido. Com n = 10, o quadrado dá 100 voltas; com n = 1000, dá um milhão; com três laços aninhados de 1000, um bilhão. Quando um programa com laços aninhados fica lento com muitos dados, é por isso. Por enquanto, basta lembrar: cada laço a mais multiplica o trabalho.

break e continue nos laços aninhados

Dentro de laços aninhados, break e continue agem só no laço onde estão escritos (o mais de dentro). Para sair dos dois de uma vez, use um rótulo, como break externo;. Tudo isso está explicado com exemplos reais em break e continue.


Formas diferentes

Qualquer laço pode ficar dentro de qualquer outro. Os mais comuns:

CombinaçãoExemplo de uso
for dentro de forFiguras, tabelas, as linhas e colunas de uma matriz.
for-each dentro de for-eachPara cada turma, para cada aluno da turma.
for dentro de whileEnquanto o usuário quiser continuar, desenhar uma linha de N estrelas.
Dois laços de dentro lado a ladoA pirâmide: espaços e depois estrelas, na mesma linha.
Três laçosRaros: horas, minutos e segundos; cubos de dados. Cuidado com o número de voltas.

Quando dá errado

"variable i is already defined": o mesmo nome nos dois laços
public class Main {
    public static void main(String[] args) {
        for (int i = 1; i <= 3; i++) {
            for (int i = 1; i <= 4; i++) {
                System.out.print("*");
            }
            System.out.println();
        }
    }
}
$ java Main.java
Main.java:4: error: variable i is already defined in method main(String[])
            for (int i = 1; i <= 4; i++) {
                     ^
1 error
error: compilation failed

O que quer dizer: "a variável i já foi definida no método main". O i do laço de fora ainda está vivo dentro do laço de dentro, então não dá para criar outro com o mesmo nome.

Como consertar: use um nome diferente no de dentro: j (a tradição) ou, melhor ainda, nomes que digam o que contam: linha e coluna.

Uma fila infinita de estrelas: o passo errado no laço de dentro
public class Main {
    public static void main(String[] args) {
        for (int i = 1; i <= 3; i++) {
            for (int j = 1; j <= 4; i++) {
                System.out.print("*");
            }
            System.out.println();
        }
    }
}
$ java Main.java
************************************************************   « … uma linha só, sem fim …
$ echo $?                    « depois do Ctrl+C
130

O que aconteceu: o laço de dentro testa j, mas o passo soma em i (copiar e colar o cabeçalho do laço de fora é a causa clássica). O j fica 1 para sempre, a condição j <= 4 nunca fica falsa e o programa escreve estrelas sem parar, todas na mesma linha (o println nunca é alcançado). Em um segundo, foram mais de 200 mil estrelas até a Ana apertar Ctrl+C.

Como consertar: confira as três partes do cabeçalho de dentro: todas devem usar a mesma variável (j = 1; j <= 4; j++).

Todas as estrelas numa coluna só: println no lugar de print
public class Main {
    public static void main(String[] args) {
        for (int linha = 1; linha <= 3; linha++) {
            for (int coluna = 1; coluna <= 5; coluna++) {
                System.out.println("*");
            }
        }
    }
}
$ java Main.java
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*

O que aconteceu: as 15 estrelas estão certas (3 × 5), mas cada println pula a linha. O retângulo virou uma coluna.

Como consertar: dentro do laço de dentro, print; depois dele, no laço de fora, um println() para fechar a linha.

O desenho sai "torto" ou com uma linha a mais

Confira o lugar do println(): se ele estiver dentro do laço de dentro, cada estrela fica numa linha; se estiver fora dos dois laços, tudo sai numa linha só. O lugar certo é dentro do de fora, logo depois do } do de dentro. Uma boa indentação (o recuo das linhas) mostra isso de relance; mantenha cada laço quatro espaços mais para dentro que o anterior.


Referência

PadrãoLaço de foraLaço de dentroVoltas do de dentro (total)
Retângulo L × Clinha de 1 a Lcoluna de 1 a CL × C
Triângulolinha de 1 a Ncoluna de 1 a linha1 + 2 + … + N
Triângulo invertidolinha de N a 1coluna de 1 a linhaN + … + 2 + 1
Pirâmide de altura Alinha de 1 a AA - linha espaços, depois 2*linha - 1 estrelasA² estrelas
Tabela de multiplicaçãoi de 1 a 10j de 1 a 10, mostra i * j100

Exercícios

1. O limite do triângulo

Complete o laço de dentro para desenhar um triângulo (1, 2, 3… estrelas por linha):

for (int coluna = 1; coluna <= ; coluna++)

2. Fechar a linha

Complete a instrução que vai logo depois do laço de dentro, para cada linha do desenho terminar:

3. Quantas voltas?

Quantas vezes o print roda em for (int i = 0; i < 4; i++) for (int j = 0; j < 6; j++) System.out.print("*");?

vezes

4. Em dois laços aninhados, quando o laço de dentro "recomeça do início"?

5. Qual figura este código desenha? for (int l = 3; l >= 1; l--) { for (int c = 1; c <= l; c++) System.out.print("*"); System.out.println(); }

6. Com três laços aninhados, cada um de 1 a 100, quantas vezes o corpo mais de dentro roda?

Missão final: desenhe um triângulo de números com 4 linhas: a linha 1 mostra 1 , a linha 2 mostra 1 2 , a linha 3 mostra 1 2 3 e a linha 4 mostra 1 2 3 4 (cada número seguido de um espaço). Dica: é o triângulo de estrelas, trocando "*" pela variável do laço de dentro.

public class Main {
    public static void main(String[] args) {
        for (int linha = 1; linha <= 4; linha++) {
            // laço de dentro aqui

            System.out.println();
        }
    }
}
public class Main {
    public static void main(String[] args) {
        for (int linha = 1; linha <= 4; linha++) {
            for (int coluna = 1; coluna <= linha; coluna++) {
                System.out.print(coluna + " ");
            }
            System.out.println();
        }
    }
}

Resumo

  • Um laço dentro de outro: para cada volta do de fora, o de dentro roda inteiro, recomeçando do início.
  • Para figuras e tabelas: o de fora são as linhas, o de dentro são as colunas (com print), e um println() fecha cada linha.
  • Triângulo: o limite do de dentro é a variável do de fora (coluna <= linha).
  • Total de voltas com limites fixos = multiplicação dos limites. Cada laço a mais multiplica o trabalho.
  • Use nomes diferentes em cada laço (i/j, ou melhor, linha/coluna) e confira se as três partes de cada cabeçalho usam a mesma variável.
  • break e continue agem no laço mais de dentro; para sair dos dois, use um rótulo (break e continue).