Padrão Iterator
Parte da seção Programação Orientada a Objetos do Journey de Java da Coddy — lição 76 de 87.
O Iterator Pattern é um padrão de design comportamental que fornece uma maneira de acessar elementos de uma coleção sequencialmente sem expor sua estrutura subjacente. Esteja você trabalhando com um array, lista encadeada ou árvore, o iterador oferece uma maneira uniforme de percorrer os elementos.
O padrão separa a lógica de travessia da própria coleção. Ele envolve dois componentes principais: uma interface Iterator que define métodos para percorrer elementos, e um Iterable (ou Aggregate) que cria iteradores para sua coleção:
interface Iterator<T> {
boolean hasNext();
T next();
}
interface Container<T> {
Iterator<T> createIterator();
}
class BookShelf implements Container<String> {
private String[] books;
private int count = 0;
public BookShelf(int size) {
books = new String[size];
}
public void addBook(String book) {
books[count++] = book;
}
public Iterator<String> createIterator() {
return new BookIterator();
}
private class BookIterator implements Iterator<String> {
private int index = 0;
public boolean hasNext() {
return index < count;
}
public String next() {
return books[index++];
}
}
}O iterador mantém seu próprio estado de iteração, permitindo que múltiplos iteradores percorram a mesma coleção de forma independente. Os clientes usam o iterador sem saber como a coleção armazena seus dados:
BookShelf shelf = new BookShelf(3);
shelf.addBook("Design Patterns");
shelf.addBook("Clean Code");
Iterator<String> iterator = shelf.createIterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}As interfaces integradas Iterable e Iterator do Java seguem exatamente este padrão, razão pela qual você pode usar loops for aprimorados com qualquer classe que implemente Iterable. O Padrão Iterator é essencial quando você precisa fornecer múltiplos métodos de travessia ou ocultar estruturas internas complexas do código do cliente.
Desafio
FácilVamos construir um sistema de playlist usando o Iterator Pattern! Você criará uma playlist de música que armazena músicas e fornece um iterador personalizado para percorrê-las sequencialmente — sem expor como as músicas são armazenadas internamente. Este é um caso de uso perfeito para o Iterator Pattern, permitindo que os usuários naveguem em sua coleção por meio de uma interface limpa e uniforme.
Você organizará seu código em quatro arquivos:
Iterator.java: Defina sua interface genéricaIterator<T>com dois métodos:hasNext()que retorna um booleano indicando se existem mais elementos, enext()que retorna o próximo elemento do tipo T.Playlist.java: Crie a classe agregada que contém suas músicas. SuaPlaylistdeve armazenar músicas em um array de String com uma capacidade fixa (passada para o construtor) e rastrear quantas músicas foram adicionadas. Inclua um métodoaddSong(String song)para adicionar músicas à playlist.Sua Playlist precisa de um método
createIterator()que retorne umIterator<String>. Implemente isso criando uma classe interna privada chamadaPlaylistIteratorque implementa sua interface Iterator. Este iterador interno mantém sua própria posição de índice e percorre o array de músicas, retornando cada música em ordem.Song.java: Crie uma classeSongsimples que envolve o título de uma música. Ela deve ter um construtor que recebe o título (String), um métodogetTitle()e um métodotoString()que retorna"Playing: " + title.Main.java: Reúna seu sistema de iterador! Você receberá uma entrada: uma lista de títulos de músicas separados por vírgula (por exemplo:"Bohemian Rhapsody,Stairway to Heaven,Hotel California").Crie uma Playlist com capacidade para 10 músicas. Analise a entrada e adicione cada título de música à playlist. Em seguida, obtenha um iterador da playlist e use-o para percorrer todas as músicas, imprimindo cada uma envolvida em um objeto Song (que será exibido como
"Playing: " + title).Após iterar por todas as músicas, imprima
"Playlist complete!"em uma nova linha.
Você receberá uma entrada: uma string de títulos de músicas separados por vírgula.
Por exemplo, com a entrada "Yesterday,Imagine,Let It Be", sua saída seria:
Playing: Yesterday
Playing: Imagine
Playing: Let It Be
Playlist complete!Observe como sua classe Main usa os métodos hasNext() e next() do iterador para percorrer a playlist sem saber nada sobre a estrutura do array subjacente. O iterador encapsula toda a lógica de travessia, mantendo a representação interna da coleção oculta do código do cliente!
Folha de consulta
O Iterator Pattern (Padrão Iterator) é um padrão de projeto comportamental que fornece uma maneira de acessar elementos de uma coleção sequencialmente sem expor sua estrutura subjacente.
O padrão separa a lógica de travessia da própria coleção usando dois componentes principais:
- Interface Iterator: define métodos para percorrer elementos
- Iterable/Container: cria iteradores para sua coleção
Estrutura Básica
interface Iterator<T> {
boolean hasNext();
T next();
}
interface Container<T> {
Iterator<T> createIterator();
}Exemplo de Implementação
class BookShelf implements Container<String> {
private String[] books;
private int count = 0;
public BookShelf(int size) {
books = new String[size];
}
public void addBook(String book) {
books[count++] = book;
}
public Iterator<String> createIterator() {
return new BookIterator();
}
private class BookIterator implements Iterator<String> {
private int index = 0;
public boolean hasNext() {
return index < count;
}
public String next() {
return books[index++];
}
}
}Uso
BookShelf shelf = new BookShelf(3);
shelf.addBook("Design Patterns");
shelf.addBook("Clean Code");
Iterator<String> iterator = shelf.createIterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}O iterador mantém seu próprio estado de travessia, permitindo que múltiplos iteradores percorram a mesma coleção de forma independente. As interfaces integradas Iterable e Iterator do Java seguem este padrão, habilitando loops for aprimorados (enhanced for-loops).
Experimente você mesmo
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine();
// TODO: Crie uma Playlist com capacidade para 10 músicas
// TODO: Analise a entrada (separada por vírgulas) e adicione o título de cada música à playlist
// TODO: Obtenha um iterator da playlist usando createIterator()
// TODO: Use o iterator para percorrer todas as músicas
// Para cada música, envolva-a em um objeto Song e imprima-o
// TODO: Imprima "Playlist complete!" após iterar por todas as músicas
}
}
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Programação Orientada a Objetos
1Fundamentos de POO
Arquivos ExternosIntrodução à POOClasses vs ObjetosA Palavra-chave thisMétodosCampos (Atributos)Método ConstrutorSobrecarga de ConstrutorRecapitulação - Calculadora Simples4Herança
Herança Básica (extends)A Palavra-chave superSobrescrita de Método (@Override)Encadeamento de ConstrutoresA Classe ObjectHerança Simples e MultinívelPor que não há Herança Múltipla de ClassesRecapitulação - Hierarquia de Funcionários7Métodos Especiais e a Classe Object
Método toString()equals() e hashCode()Método clone()compareTo() e ComparableInterface ComparatorRecapitulação - Ordenação Personalizada2Modificadores de Acesso e Encapsulamento
Visão Geral dos Níveis de AcessoMétodos Getter e SetterOcultação de InformaçõesA Palavra-chave finalRecapitulação - Gerenciador de Conta Bancária5Polimorfismo
Fundamentos de Sobrecarga de MétodosSobrescrita de Métodos (Tempo de Execução)Upcasting e DowncastingO Operador instanceofClasses e Métodos AbstratosRecapitulação - Calculadora de Formas8Conceitos Avançados de OOP
Composição vs HerançaAgregação vs ComposiçãoClasses Internas, Aninhadas e AnônimasEnums e Métodos de EnumRecords (Java 16+)Classes Seladas (Java 17+)11Padrões de Projeto Parte 1
Introdução aos Padrões de ProjetoPadrão SingletonPadrão FactoryPadrão BuilderPadrão ObserverPadrão Strategy3Propriedades de Classe e Membros Estáticos
Variáveis de Instância vs EstáticasMétodos EstáticosBlocos EstáticosConstantes (static final)Recapitulação - Contador e Utilitário6Interfaces e Classes Abstratas
Introdução às InterfacesImplementando InterfacesImplementação de Múltiplas InterfacesDefault e Static em InterfacesClasses Abstratas vs InterfacesInterfaces FuncionaisRecapitulação - Sistema de Pagamento9Generics
Introdução a GenericsClasses GenéricasMétodos GenéricosParâmetros de Tipos DelimitadosWildcards (?, extends, super)Recapitulação - Container Genérico12Padrões de Projeto Parte 2
Padrão CommandPadrão AdapterPadrão DecoratorPadrão Template MethodPadrão StatePadrão CompositePadrão Iterator