08 Jan 2025

Iterator Pattern

Overview

The Iterator Pattern is a behavioral design pattern that provides a way to access elements of a collection (aggregate object) sequentially without exposing its underlying representation. It decouples the traversal logic from the actual collection, allowing flexibility and reusability.

Key Participants

  1. Iterator

  • Defines the interface for accessing and traversing elements (e.g., hasNext(), next()).

  1. Concrete Iterator

  • Implements the Iterator interface.

  • Keeps track of the current position in the traversal of the collection.

  1. Aggregate (Collection)

  • Defines the interface for creating an iterator (e.g., createIterator()).

  1. Concrete Aggregate

  • Implements the Aggregate interface.

  • Stores the collection of elements and creates an iterator to traverse them.

Implementation in Code

Example: Custom Collection of Names

import java.util.List;
import java.util.ArrayList;

// Iterator Interface
interface Iterator<T> {
    boolean hasNext();
    T next();
}

// Concrete Iterator
class NameIterator implements Iterator<String> {
    private List<String> names;
    private int position = 0;

    public NameIterator(List<String> names) {
        this.names = names;
    }

    @Override
    public boolean hasNext() {
        return position < names.size();
    }

    @Override
    public String next() {
        if (this.hasNext()) {
            return names.get(position++);
        }
        return null;
    }
}

// Aggregate Interface
interface Collection<T> {
    Iterator<T> createIterator();
}

// Concrete Aggregate
class NameCollection implements Collection<String> {
    private List<String> names = new ArrayList<>();

    public void addName(String name) {
        names.add(name);
    }

    @Override
    public Iterator<String> createIterator() {
        return new NameIterator(names);
    }
}

// Client
public class IteratorPatternDemo {
    public static void main(String[] args) {
        NameCollection nameCollection = new NameCollection();
        nameCollection.addName("Alice");
        nameCollection.addName("Bob");
        nameCollection.addName("Charlie");

        Iterator<String> iterator = nameCollection.createIterator();

        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }
}

Key Methods

  1. hasNext(): Checks if there are more elements in the collection.

  1. next(): Retrieves the next element in the collection.

Advantages

  1. Encapsulation: Hides the internal structure of the collection.

  1. Uniform Traversal: Provides a standard way to traverse collections regardless of their implementation.

  1. Reusability: Iterators can be reused across different collections with consistent interfaces.

  1. Multiple Iterators: Supports multiple iterators to traverse the same collection independently.

Disadvantages

  1. Overhead: Adding iterator logic can increase complexity and memory usage.

  1. Limited Access: Iterators typically provide sequential access, not random access.

Real-World Examples

  1. Java Collections Framework: Iterators for lists, sets, and maps (e.g., Iterator interface in Java).

  1. File Systems: Traversing files and directories in a file system.

  1. Social Media Feeds: Iterating over posts in a timeline or news feed.

When to Use the Iterator Pattern?

  • When you need a standard way to traverse different types of collections.

  • When you want to decouple the traversal logic from the collection’s internal structure.

  • When you need multiple ways to traverse the same collection (e.g., forward, backward).

← Back to Library