Java Notes
Learn the Iterator interface in Java — how to traverse collections safely, remove elements during iteration, ListIterator for bidirectional traversal, and the for-each loop internals.
When you use a for-each loop on a collection, Java internally uses an Iterator — an object that knows how to move through the collection one element at a time. Understanding Iterator directly gives you more control, especially when you need to remove elements while traversing.
The Iterator Interface
Three methods:
public interface Iterator<E> {
boolean hasNext(); // true if there are more elements
E next(); // returns the next element, moves cursor forward
void remove(); // removes the last element returned by next()
}Basic Usage
Try it in WoHoCode
Edit the program, then run it here.
Run this example to see its output.
Line by line:
fruits.iterator()— creates an Iterator object positioned before the first element.it.hasNext()— returns true if there is another element ahead.it.next()— moves to the next element and returns it.- After
cherry,hasNext()returns false and the loop stops.
This is exactly what the for-each loop does internally. The for-each is just shorter syntax for this.
Removing Elements During Iteration
This is the most important use of explicit Iterator. You cannot remove from a collection using for-each — it throws ConcurrentModificationException. Use it.remove() instead.
Try it in WoHoCode
Edit the program, then run it here.
Run this example to see its output.
Line by line:
it.remove()— removes the element thatnext()last returned. Safe because the Iterator itself manages the removal.- Calling
it.remove()without callingit.next()first throwsIllegalStateException. - Using
numbers.remove(num)inside the loop instead would throwConcurrentModificationException.
Why For-Each Throws ConcurrentModificationException
Collections track how many times they have been modified using an internal counter. When an Iterator is created, it records that count. If the count changes during iteration (meaning the collection was modified externally), the iterator throws the exception.
Try it in WoHoCode
Edit the program, then run it here.
Run this example to see its output.
ListIterator — Bidirectional Traversal
ListIterator extends Iterator and works only on List implementations. It can go forward and backward, and can add/set elements during traversal.
Try it in WoHoCode
Edit the program, then run it here.
Run this example to see its output.
Line by line:
lit.nextIndex()— the index of the element thatnext()would return.lit.hasPrevious()/lit.previous()— move backwards through the list.modifier.set(...)— replaces the element last returned bynext()orprevious().
Iterator vs For-Each — When to Use Which
| Situation | Use |
|---|---|
| Just reading elements | for-each — shorter, cleaner |
| Removing elements while traversing | Iterator.remove() |
| Replacing elements while traversing | ListIterator.set() |
| Traversing backwards | ListIterator |
| Adding elements while traversing | ListIterator.add() |
Common Mistake 1: Calling next() Without Checking hasNext()
Iterator<String> it = list.iterator();
// WRONG — if list is empty, throws NoSuchElementException
String first = it.next();
// CORRECT
if (it.hasNext()) {
String first = it.next();
}Common Mistake 2: Calling remove() Without a Prior next()
Iterator<String> it = list.iterator();
// WRONG — no next() was called yet
it.remove(); // IllegalStateException
// CORRECT
while (it.hasNext()) {
it.next();
it.remove(); // valid — after next()
}Common Mistake 3: Using Iterator After Modification Outside It
Iterator<String> it = list.iterator();
it.next();
list.add("extra"); // modifies the list outside the iterator
it.next(); // ConcurrentModificationException — modCount changed
// CORRECT — do not modify the list outside the iterator while iteratingPractice Task
Task: Given a List<Integer> with values {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, use an Iterator to:
- Remove all even numbers from the list
- Print the remaining numbers
Also, use a ListIterator to traverse the same list backwards after removal and print in reverse.
Hint: After removing evens with Iterator, create a new ListIterator on the same list, call hasNext() until the end, then loop with hasPrevious().
Solution:
Try it in WoHoCode
Edit the program, then run it here.
Run this example to see its output.
What to observe: numbers.listIterator(numbers.size()) starts the iterator after the last element — so hasPrevious() is true immediately. Try printing the nextIndex() at each step in the forward loop to see how position tracking works.
Continue the lesson path