What is the difference between Iterator and ListIterator?
LinkedList.get(i) starts from head/tail each time and steps i times through links. ListIterator reaches the needed node once and then moves with O(1) — it stores a reference to...
🟢 Junior Level
Iterator — for iterating over any collections (forward only). ListIterator — for lists (forward and backward).
// Iterator: works with List, Set, Queue
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String s = it.next();
}
// ListIterator: List only, but more powerful
ListIterator<String> it = list.listIterator();
while (it.hasNext()) {
String s = it.next();
// Can go backward!
if (it.hasPrevious()) {
String prev = it.previous();
}
}
🟡 Middle Level
Comparison
| Iterator | ListIterator | |
|---|---|---|
| Collections | All (List, Set, Queue) | List only |
| Direction | Forward only | Forward and backward |
| Indices | No | nextIndex(), previousIndex() |
| Modification | remove() | remove(), set(), add() |
| Start | From the beginning | From any index |
Cursor between elements
List: [A] [B] [C]
↑
Cursor (between A and B)
it.next() → returns B, cursor moves right
it.previous() → returns A, cursor moves left
ListIterator vs for (int i...): for (int i...) for LinkedList = O(n^2), because each get(i) iterates from the start. ListIterator = O(n), because it remembers the current position. For ArrayList, both approaches are O(n).
LinkedList optimization
// ❌ O(n²) — each get iterates!
for (int i = 0; i < list.size(); i++) {
list.get(i); // O(n) for LinkedList
}
// ✅ O(n) — iterator is already in place
ListIterator<String> it = list.listIterator();
while (it.hasNext()) {
it.next(); // O(1)
it.add("new"); // O(1) — already at the node!
}
LinkedList.get(i) starts from head/tail each time and steps i times through links. ListIterator reaches the needed node once and then moves with O(1) — it stores a reference to the current Node.
🔴 Senior Level
When NOT to use ListIterator
- Working with Set/Queue — ListIterator is not supported
- Simply reading elements — for-each is cleaner
- Need parallel processing — Iterator is simpler
Modification methods
// add(E) — inserts BEFORE the cursor
it.add("X");
// it.previous() will return "X"
// set(E) — replaces the LAST element returned by next/previous
it.next(); // → "A"
it.set("B"); // "A" → "B"
// ❌ IllegalStateException if next/previous was not called
it.set("X"); // Error!
forEachRemaining (Java 8+)
Iterator<String> it = list.iterator();
it.forEachRemaining(System.out::println);
// → Remaining elements
LinkedList optimization
LinkedList.get(500) → 500 node traversals
ListIterator at position 500:
→ add/remove/set → O(1)
→ Already holds a reference to the Node!
Best Practices
- Iterator → for all collections
- ListIterator → for List, especially LinkedList
- Cursor between elements
- set/add depend on the last next/previous
- listIterator(index) → start from a position
- forEachRemaining → Java 8+ functional style
Summary for Senior
- Iterator = universal, forward only
- ListIterator = List, bidirectional, modification
- Cursor between elements
- LinkedList → ListIterator is critical for O(1)
- set/add → after next/previous
🎯 Interview Cheat Sheet
Must know:
Iteratorworks with all collections (List, Set, Queue), forward onlyListIteratorfor List only, but supports: backward movement, indices,set(),add()- ListIterator cursor is BETWEEN elements —
next()returns the element to the right,previous()— to the left - For LinkedList:
for (int i...)= O(n^2),ListIterator= O(n) set()andadd()work only after callingnext()orprevious()listIterator(index)allows starting iteration from any positionforEachRemaining()(Java 8+) — functional style for remaining elements
Frequent follow-up questions:
- Why is
for (int i...)for LinkedList O(n^2)? — Eachget(i)steps from the start/end through nodes; n calls × n steps = O(n^2). - When does ListIterator.add(“X”) insert the element? — Before the cursor; the next
previous()will return “X”. - Can ListIterator be used with HashSet? — No, Set does not support ListIterator — only regular Iterator.
- What happens if you call set() without a prior next()? —
IllegalStateException— there is no “last element” to replace.
Red flags (DO NOT say):
- “ListIterator works with Set” — no, only with List
- “Iterator can move backward” — no, only ListIterator has
previous() - “
for (int i...)and ListIterator are equally efficient for LinkedList” — no, O(n^2) vs O(n) - “
set()replaces the next element” — no, it replaces the last one returned bynext()/previous()
Related topics:
- [[28. How to properly remove elements during iteration]]
- [[26. What are fail-fast and fail-safe iterators]]
- [[27. What is ConcurrentModificationException]]