Card 05/ 09
Factory Method in the Wild: Java's Collection.iterator()
Every collection hands back its own iterator, and the for loop never names the class.
Java's collections library uses Factory Method in a method most Java developers call daily without seeing it: iterator(). Collection declares it, each collection class overrides it to return its own iterator class, and the code that loops never learns which one it received. This card shows the concrete classes behind that one method.
The listing asks five collections for an iterator and prints the class of what comes back.
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.TreeSet;
public class FmIterators {
public static void main(String[] args) {
List<Collection<String>> collections = List.of(
new ArrayList<>(List.of("a")),
new LinkedList<>(List.of("a")),
new HashSet<>(List.of("a")),
new TreeSet<>(List.of("a")),
new ArrayDeque<>(List.of("a")));
for (Collection<String> collection : collections) {
System.out.println(collection.getClass().getSimpleName()
+ " -> " + collection.iterator().getClass().getName());
}
}
}ArrayList -> java.util.ArrayList$Itr
LinkedList -> java.util.LinkedList$ListItr
HashSet -> java.util.HashMap$KeyIterator
TreeSet -> java.util.TreeMap$KeyIterator
ArrayDeque -> java.util.ArrayDeque$DeqIteratorThe five collections return five different iterator classes. The $ in a name such as ArrayList$Itr marks a class declared inside another, so Itr is a private class inside ArrayList. A HashSet stores its elements as the keys of a HashMap, which is why it hands back the map's key iterator. You could not create these classes yourself if you tried, and a for-each loop has no need to: it calls iterator() and uses the result as an Iterator.
| Participant | In the Java collections library |
|---|---|
| Creator | Collection (through Iterable), which declares iterator() |
| ConcreteCreator | ArrayList, LinkedList, HashSet and the others |
| Product | Iterator, the interface every result implements |
| ConcreteProduct | ArrayList$Itr, LinkedList$ListItr and the other private classes |
| Factory method | iterator() |
What this case shares with the notification sender is the shape, not the domain: a method on the creator returns a product through an interface, each subclass decides the concrete class, and the caller never names it. In the notifier the caller was the creator's own notify_shipped; here it is the for-each loop and any other code that holds a Collection.
The class names are implementation details of OpenJDK, as run here on Java 21, and could change in a later release without breaking any program, because no program names them.
← → move through sections and cards