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