Java > Design Patterns in Java > Behavioral Patterns > Iterator Pattern
Iterator Pattern Demonstration in Java
The Iterator Pattern provides a way to access the elements of an aggregate object sequentially without exposing its underlying representation. This example showcases a simple implementation of the Iterator pattern using a collection of names.
Implementation
This code demonstrates the Iterator pattern with a `NameRepository` that holds a list of names. The `Aggregate` interface defines the `createIterator()` method, which is implemented by `NameRepository`. The `NameIterator` inner class implements the `Iterator` interface, providing the `hasNext()` and `next()` methods to traverse the names.
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
interface Aggregate {
Iterator<String> createIterator();
}
class NameRepository implements Aggregate {
private final List<String> names = new ArrayList<>();
public NameRepository(String... names) {
this.names.addAll(List.of(names));
}
@Override
public Iterator<String> createIterator() {
return new NameIterator();
}
private class NameIterator implements Iterator<String> {
int index;
@Override
public boolean hasNext() {
return index < names.size();
}
@Override
public String next() {
if (this.hasNext()) {
return names.get(index++);
}
return null;
}
}
}
public class IteratorPatternDemo {
public static void main(String[] args) {
NameRepository nameRepository = new NameRepository("Robert", "John", "Julie", "Lora");
for (Iterator<String> iter = nameRepository.createIterator(); iter.hasNext(); ) {
String name = iter.next();
System.out.println("Name : " + name);
}
}
}
Concepts Behind the Snippet
The key concepts are the `Aggregate` interface (representing the collection), the `Iterator` interface (defining traversal methods), and concrete implementations of both. This separation allows the client to traverse the collection without knowing its internal structure.
Real-Life Use Case
Iterators are heavily used in Java collections framework (e.g., `ArrayList`, `LinkedList`, `HashSet`). Whenever you use a `for-each` loop on a collection, you're implicitly using an iterator.
Best Practices
Interview Tip
Be prepared to explain the difference between an Iterator and an Enumeration. Also, be ready to discuss how the Iterator pattern promotes loose coupling and simplifies collection traversal.
When to Use Them
Use the Iterator pattern when:
Memory Footprint
The Iterator itself typically has a small memory footprint, usually consisting of an index or a reference to the current element. The memory consumption is primarily determined by the underlying collection being iterated over.
Alternatives
Alternatives to the Iterator pattern include:
Pros
Cons
Can add complexity to the design, especially for simple collections where direct access might be sufficient. Requires maintaining iterator state, which can be tricky in concurrent scenarios.
FAQ
-
What happens if I modify the collection while iterating using the Iterator?
Modifying the collection (adding or removing elements) while iterating using the Iterator can lead to a `ConcurrentModificationException`. To avoid this, use the iterator's `remove()` method if available, or use a thread-safe collection. -
What is the difference between an Iterator and an Enumeration?
The primary difference is that `Iterator` has `remove()` method (allows removing elements during iteration), while `Enumeration` does not. Also, `Iterator` method names are shorter (`hasNext()` vs. `hasMoreElements()`, `next()` vs. `nextElement()`).