The java.util.Iterator is an interface used to cycle through a collection one element at a time. It is the "Cursor" of the Java world, allowing you to access elements and—crucially—remove them safely during the process.
A standard for(int i=0; i < list.size(); i++) works for Lists because they have indices. But what about a Set? Sets don't have indices. An Iterator provides a common language for all collections.
next(), it jumps over the next element and hands it to you.
The Iterator interface is remarkably simple, consisting of three primary methods that handle the entire lifecycle of traversal:
| Method | Description |
|---|---|
boolean hasNext() |
Returns true if the collection has more elements. It’s the "safety check." |
E next() |
Returns the next element and moves the cursor forward. |
void remove() |
Removes the last element returned by the iterator from the collection. |
This is the #1 reason to use an Iterator. If you try to remove an item from a list using a standard for-each loop, Java will throw a ConcurrentModificationException. This is because the loop is "reading" while you are "writing," causing the collection's internal state to become inconsistent.
The Iterator’s remove() method is the only safe way to modify a collection while you are currently iterating through it.
While Iterator works for all collections, there is a specialized version for Lists called ListIterator. It adds powerful bidirectional capabilities:
remove().add(), set(), and remove().In this example, we iterate through a list of scores and remove any that are below the passing threshold. Notice how the Iterator handles the removal without crashing.
Iterators in the standard Java Collections (ArrayList, HashSet, etc.) are Fail-Fast. This means if the collection is modified by anything other than the Iterator's own methods while iteration is in progress, the Iterator will immediately throw an exception.
Classes in java.util.concurrent (like CopyOnWriteArrayList) provide Fail-Safe iterators that work on a clone of the data, allowing concurrent modifications without crashing.
Since Java 8, we often use list.forEach(item -> ...). While this looks different, under the hood, Java is still using an Iterator! The Iterable interface is the parent of Collection, and it is what allows an object to be targeted by the "for-each" loop or the forEach() method.
Q: What is the difference between Enumeration and Iterator?
A: Enumeration is the legacy version (used for Vector/Hashtable). It can only read data. Iterator is modern and allows for removal of elements.
Q: Can you move an Iterator backwards?
A: A standard Iterator cannot. However, a ListIterator can move backwards using hasPrevious() and previous().
Q: Why does next() return an Object/Generic instead of just moving?
A: It follows the "Consumer" pattern. It ensures that the act of moving and the act of retrieving are coupled so that you never "skip" an element accidentally.
The Iterator is the unsung hero of the Java Collections Framework. While we often take it for granted via the for-each loop, understanding the Iterator is essential for handling complex logic like conditional removals and bidirectional navigation. It provides the "Glue" that allows Java's various data structures to be treated with a single, unified logic.
Next: Mastering List Sorting →