Because iterators are like snapshots of your collection at a certain moment in time.
Let’s say:
- You create an
Iterator
to walk through a list. - The iterator expects the structure of the list to stay the same while it’s walking.
- If you suddenly change the structure (like adding/removing elements), the iterator gets confused.
It’s like someone walking through a building while you’re tearing down walls around them — it’s dangerous and unpredictable! 😅
🔧 How does Java protect us?
Java uses a counter inside collections — modCount
.
When you:
- Add/remove/clear a collection →
modCount
increases. - An iterator checks if
modCount
is still the same as when it started.
If not, it throws:
ConcurrentModificationException
This is fail-fast behavior: better crash early than produce wrong results silently.
📦 Analogy: Parcel Delivery
Imagine:
- A delivery person (iterator) picks up a list of houses (your collection).
- You suddenly add/remove houses while they’re delivering.
- The list is now invalid! They don’t know where to go → boom 💥 error.
✅ When is it safe to modify?
Only through the iterator’s own method:
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String value = it.next();
if (value.equals("deleteMe")) {
it.remove(); // safe!
}
}
Why? Because the iterator knows you’re removing something — it updates itself safely.
🤔 But why not allow changes automatically?
Because:
- It’s complex to track all changes during iteration.
- It could lead to bugs and unexpected behavior.
- Java chose to protect the developer instead of hiding dangerous mistakes.
If you really need to modify a collection during iteration, use:
CopyOnWriteArrayList
(safe for concurrent modification)- Create a copy of the list and iterate over the copy
- Use streams + filters to create new collections instead of modifying the original