Iterator Pattern : A Simple Explanation
Situation: You’re Dealing with a List of Users
You’ve got a List<User>
from the database.
You want to go through this list and:
- Send emails
- Log activity
- Filter some out
Easy, right? So you write:
for (int i = 0; i < users.size(); i++) {
User u = users.get(i);
// do something
}
Then Things Get Ugly
Suddenly, your collection isn’t always a List anymore:
- Sometimes it’s a
Set<User>
- Sometimes it’s a
Queue<User>
- Sometimes a custom data structure (like
Tree<User>
or a weird in-house object)
Now your code is littered with:
if (collection instanceof List) {
// loop one way
} else if (collection instanceof Set) {
// different loop
} else if ...
You’re stuck in type-checking hell just to loop through elements.
What’s the Real Problem?
- You’re writing looping logic that’s tied to how data is stored
- You can’t swap data structures without rewriting your logic
- Your business logic is now tightly coupled to the internal structure of the collection
It’s fragile, repetitive, and breaks the Single Responsibility Principle
How Iterator Pattern Saves You
Iterator says:
“Stop caring about how the collection is built. I’ll give you a uniform way to walk through it - safely.”
So now:
- Every collection gives you an Iterator
- That iterator has
.hasNext()
and.next()
methods - You don’t care if the data is a List, Set, or custom tree, the loop looks the same
You focus on what you want to do, not how to get to each element
class NameCollection {
private final String[] names = {"Name1", "Name2", "Name3", "Name4"};
public MyIterator iterator() {
return new NameIterator();
}
private class NameIterator implements MyIterator {
private int index = 0;
public boolean hasNext() {
return index < names.length;
}
public String next() {
return names[index++];
}
}
}
When to Use Iterator?
- When you want to traverse collections without knowing their internals
- When you want a common interface to loop through any collection
- When building custom collections but still want them loopable