0Pricing
Java Academy · Aula

Contratos de Iterable e Iterator

Compreenda as interfaces Iterable e Iterator e como os laços for-each funcionam internamente.

Contratos de Iterable e Iterator é uma aula grátis de Java Academy no CoddyKit. Esta é a aula 1 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Java Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Java Academy inclui 4 aulas no total.

Iterable e Iterator

Iterable<T> e Iterator<T> são as interfaces que dão suporte ao laço de iteração de Java. Compreendê-las permite criar suas próprias estruturas de dados compatíveis com laços.

A interface Iterable

Iterable<T> tem um método: iterator(), que retorna um Iterator<T>. Qualquer classe que implemente Iterable pode ser usada em um laço de iteração.

// java.lang.Iterable<T>
interface Iterable<T> {
    Iterator<T> iterator();
    // default: forEach, spliterator (Java 8+)
}

// Any class implementing Iterable<T> works in for-each:
class Range implements Iterable<Integer> {
    private final int start, end;
    Range(int start, int end) { this.start = start; this.end = end; }

    public Iterator<Integer> iterator() {
        return new RangeIterator(); // defined separately
    }
}

A interface Iterator

Iterator<T> tem três métodos: hasNext(), next() e o método opcional remove().

// java.util.Iterator<T>
interface Iterator<T> {
    boolean hasNext(); // true if more elements
    T next();          // returns next element, advances cursor
    default void remove() { throw new UnsupportedOperationException(); }
}

// How for-each desugars internally:
// for (T item : iterable) { use(item); }
// becomes:
Iterator<T> it = iterable.iterator();
while (it.hasNext()) {
    T item = it.next();
    // use(item)
}

Expansão do laço de iteração

O laço de iteração é um açúcar sintático sobre o padrão Iterable/Iterator. Compreender isso ajuda você a escrever Iterable personalizados corretamente.

List<String> names = List.of("Alice", "Bob", "Charlie");

// For-each (readable way)
for (String name : names) {
    System.out.println(name);
}

// Equivalent explicit form
Iterator<String> it = names.iterator();
while (it.hasNext()) {
    String name = it.next();
    System.out.println(name);
}

Estado do cursor de Iterator

Um Iterator mantém um cursor — uma posição na sequência. Chamar next() move o cursor para a frente. Depois de esgotado, o iterador não pode ser reiniciado.

List<Integer> nums = List.of(1, 2, 3);
Iterator<Integer> it = nums.iterator();

System.out.println(it.hasNext()); // true
System.out.println(it.next());    // 1
System.out.println(it.next());    // 2
System.out.println(it.next());    // 3
System.out.println(it.hasNext()); // false

try {
    it.next(); // NoSuchElementException
} catch (java.util.NoSuchElementException e) {
    System.out.println("No more elements!");
}

ConcurrentModificationException

Modificar uma coleção enquanto se itera com um iterador explícito (fora de Iterator.remove()) lança ConcurrentModificationException.

List<String> list = new ArrayList<>(List.of("a", "b", "c", "d"));

// BAD: modifying collection during for-each
try {
    for (String s : list) {
        if ("b".equals(s)) list.remove(s); // ConcurrentModificationException!
    }
} catch (java.util.ConcurrentModificationException e) {
    System.out.println("Cannot modify during iteration!");
}

// GOOD: use Iterator.remove()
Iterator<String> it = list.iterator();
while (it.hasNext()) {
    if ("b".equals(it.next())) it.remove(); // safe
}
System.out.println(list); // [a, c, d]

Vários iteradores

Cada chamada a iterator() retorna um iterador novo e independente. Vários iteradores podem estar ativos simultaneamente na mesma coleção.

List<Integer> nums = List.of(1, 2, 3);

Iterator<Integer> a = nums.iterator();
Iterator<Integer> b = nums.iterator();

System.out.println(a.next()); // 1
System.out.println(b.next()); // 1 (independent cursor)
System.out.println(a.next()); // 2
System.out.println(b.next()); // 2

Iterable ou Iterator

Distinção principal:

  • Iterable: uma fonte que pode produzir iteradores — pode ser percorrida várias vezes
  • Iterator: um cursor sobre uma sequência — de uso único e com estado
// Iterable: reusable
List<String> list = List.of("x", "y");
for (String s : list) {} // OK
for (String s : list) {} // OK again — new iterator each time

// Iterator: single-use
Iterator<String> it = list.iterator();
while (it.hasNext()) it.next();
// for (String s : it) {} // compile error — Iterator is not Iterable!

Prática: Iterable personalizado para linhas de arquivo

Um leitor de arquivos que implementa Iterable para permitir percorrer suas linhas com um laço de iteração.

import java.io.*;
import java.util.*;

class FileLines implements Iterable<String>, Closeable {
    private final BufferedReader reader;

    FileLines(String path) throws IOException {
        this.reader = new BufferedReader(new FileReader(path));
    }

    public Iterator<String> iterator() {
        return new Iterator<>() {
            private String nextLine = readNext();

            private String readNext() {
                try { return reader.readLine(); }
                catch (IOException e) { return null; }
            }

            public boolean hasNext() { return nextLine != null; }
            public String next() {
                String curr = nextLine;
                nextLine = readNext();
                return curr;
            }
        };
    }

    public void close() throws IOException { reader.close(); }
}

Método padrão forEach

Java 8 adicionou um método padrão forEach(Consumer) a Iterable. Essa é uma alternativa conveniente à escrita de laços explícitos.

List<String> cities = List.of("New York", "London", "Tokyo");

// for-each loop
for (String city : cities) System.out.println(city);

// forEach with lambda
cities.forEach(city -> System.out.println(city));

// forEach with method reference (most concise)
cities.forEach(System.out::println);

// For transforming: use stream
cities.stream()
    .map(String::toUpperCase)
    .forEach(System.out::println);

Padrão Iterator na prática

Resumo de quando implementar Iterable/Iterator:

  • Estruturas de dados personalizadas (árvore, grafo, lista encadeada)
  • Sequências preguiçosas que geram elementos sob demanda
  • Sequências baseadas em recursos (linhas de arquivo, cursor de banco de dados, fila de mensagens)

Verificação rápida

Qual exceção é lançada quando você modifica uma coleção enquanto a percorre com um laço de iteração?

Recapitulação: os contratos de Iterable e Iterator

Principais conclusões:

  • Iterable tem um método: iterator() — habilita o suporte a laços de iteração
  • Iterator tem hasNext(), next() e remove() opcional
  • O laço de iteração é um açúcar sintático sobre o padrão Iterable/Iterator
  • Chame iterator() várias vezes para obter cursores novos e independentes
  • Nunca modifique uma coleção durante um laço de iteração — use Iterator.remove() em vez disso
  • Implemente Iterable em estruturas de dados personalizadas para permitir laços de iteração

Perguntas Frequentes

A aula “Contratos de Iterable e Iterator” é grátis?

Sim — o texto completo de “Contratos de Iterable e Iterator” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Java Academy, atualize para CoddyKit PRO. O curso de Java Academy inclui 4 aulas no total.

O que vou aprender em “Contratos de Iterable e Iterator”?

Compreenda as interfaces Iterable e Iterator e como os laços for-each funcionam internamente. Você pratica Java Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar Java Academy?

Nenhuma experiência prévia é necessária. Java Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 1 de 4.

Quanto tempo leva a aula “Contratos de Iterable e Iterator”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de Java Academy?

Sim. Cada aula de Java Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. Contratos de Iterable e Iterator
  2. Implementação de um Iterator Personalizado
  3. ListIterator e Percurso Bidirecional
  4. Iterators Fail-Fast versus Fail-Safe
← Voltar para Java Academy