Menu
Coddy logo textTech

Padrão Iterator

Parte da seção Programação Orientada a Objetos do Journey de Java da Coddy. Lição 76 de 87.

O padrão Iterator é um padrão comportamental de projeto que fornece uma maneira de acessar sequencialmente os elementos de uma coleção sem expor sua estrutura subjacente. Seja trabalhando com um array, uma lista encadeada ou uma á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 Agregado) 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 percurso, permitindo que vários 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, e é por isso que você pode usar loops for aprimorados com qualquer classe que implemente Iterable. O Padrão Iterator é essencial quando você precisa fornecer vários métodos de percurso ou ocultar estruturas internas complexas do código cliente.

challenge icon

Desafio

Fácil

Vamos criar um sistema de playlist usando o Padrão Iterator! Você criará uma playlist de músicas 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 Padrão Iterator, permitindo que os usuários naveguem pela 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érica Iterator<T> com dois métodos: hasNext(), que retorna um booleano indicando se existem mais elementos, e next(), que retorna o próximo elemento do tipo T.
  • Playlist.java: Crie a classe agregadora que contém suas músicas. Sua Playlist deve armazenar as músicas em um array de String com capacidade fixa (passada ao construtor) e controlar quantas músicas foram adicionadas. Inclua um método addSong(String song) para adicionar músicas à playlist.

    Sua Playlist precisa de um método createIterator() que retorne um Iterator<String>. Implemente isso criando uma classe interna privada chamada PlaylistIterator que implemente sua interface Iterator. Esse iterador interno mantém sua própria posição de índice e percorre o array de músicas, retornando cada música na ordem.

  • Song.java: Crie uma classe simples Song que encapsule o título de uma música. Ela deve ter um construtor que receba o título (String), um método getTitle() e um método toString() que retorne 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írgulas (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 encapsulada em um objeto Song (que será exibido como Playing: [title]).

    Depois de percorrer todas as músicas, imprima Playlist complete! em uma nova linha.

Você receberá uma entrada: uma string contendo títulos de músicas separados por vírgulas.

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 percurso, mantendo a representação interna da coleção oculta do código cliente!

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 cada título de 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-a
        
        // TODO: Print "Playlist complete!" after iterating through all songs
    }
}
quiz iconTeste seus conhecimentos

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

Pratique por conta própria: Compilador de Java online