Java Notes
Complete guide to Iterator, ListIterator, and Iterable interfaces in Java — internal working, fail-fast behavior, custom iterators, and enhanced for-each loop mechanics.
What is an Iterator?
An Iterator is a design pattern (and Java interface) that provides a way to traverse a collection sequentially without exposing its underlying structure. Whether you're iterating over an ArrayList, HashSet, or TreeMap, the Iterator provides a uniform interface.
public interface Iterator<E> {
boolean hasNext(); // Is there another element?
E next(); // Return the next element
default void remove(); // Remove the last returned element (optional)
default void forEachRemaining(Consumer<? super E> action); // Java 8+
}Basic Usage
import java.util.*;
public class IteratorBasics {
public static void main(String[] args) {
List<String> fruits = new ArrayList<>(Arrays.asList(
"Apple", "Banana", "Cherry", "Date", "Elderberry"
));
// Get an iterator from the collection
Iterator<String> it = fruits.iterator();
// Traverse using hasNext() and next()
while (it.hasNext()) {
String fruit = it.next();
System.out.println(fruit);
}
}
}Output:
Iterator Methods in Detail
hasNext()
Returns true if the iteration has more elements. Does not advance the cursor.
Iterator<Integer> it = Arrays.asList(1, 2, 3).iterator();
System.out.println(it.hasNext()); // true
System.out.println(it.hasNext()); // still true — doesn't advance!
System.out.println(it.next()); // 1 — NOW it advancesnext()
Returns the next element and advances the cursor. Throws NoSuchElementException if no more elements.
Iterator<Integer> it = Arrays.asList(1).iterator();
it.next(); // 1
it.next(); // NoSuchElementException!remove()
Removes the last element returned by next(). Can only be called once per next() call.
Rules for remove():
- Must call
next()beforeremove() - Cannot call
remove()twice without callingnext()in between - Throws
IllegalStateExceptionif violated
Iterator<String> it = list.iterator();
// it.remove(); // IllegalStateException — no next() called yet
it.next();
it.remove(); // OK
// it.remove(); // IllegalStateException — can't remove twiceforEachRemaining() (Java 8+)
Processes all remaining elements with a Consumer:
Iterator<String> it = Arrays.asList("A", "B", "C", "D").iterator();
it.next(); // Skip "A"
it.forEachRemaining(s -> System.out.print(s + " "));
// Output: B C DInternal Working — How ArrayList's Iterator Works
Key Points:
cursortracks the position of the next elementlastRettracks the last returned element (forremove())expectedModCountdetects structural modifications
Fail-Fast Mechanism
What is Fail-Fast?
Iterators from most Java collections are fail-fast — they immediately throw ConcurrentModificationException if the collection is structurally modified (add/remove) during iteration by any means OTHER than the iterator's own remove() method.
How It Works
Every collection maintains an internal modCount (modification count) that increments on structural changes. When you create an iterator, it captures the current modCount as expectedModCount. Before each next() call, it checks if they still match.
List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C", "D"));
// WRONG — Modifying through the list during iteration
for (String s : list) {
if (s.equals("B")) {
list.remove(s); // ConcurrentModificationException!
}
}Why This Happens with for-each
The enhanced for-each loop is syntactic sugar for Iterator:
// This:
for (String s : list) { ... }
// Compiles to:
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String s = it.next(); // Checks modCount here — throws CME!
...
}Safe Alternatives
// 1. Use Iterator.remove()
Iterator<String> it = list.iterator();
while (it.hasNext()) {
if (it.next().equals("B")) {
it.remove(); // Safe!
}
}
// 2. Use removeIf() (Java 8+)
list.removeIf(s -> s.equals("B"));
// 3. Collect and remove later
List<String> toRemove = new ArrayList<>();
for (String s : list) {
if (s.equals("B")) toRemove.add(s);
}
list.removeAll(toRemove);
// 4. Use CopyOnWriteArrayList (fail-safe)
List<String> cowList = new CopyOnWriteArrayList<>(list);
for (String s : cowList) {
cowList.remove(s); // No CME — iterates over snapshot
}ListIterator — Bidirectional Iteration
ListIterator extends Iterator with bidirectional traversal and modification capabilities. Only available for List implementations.
public interface ListIterator<E> extends Iterator<E> {
boolean hasNext();
E next();
boolean hasPrevious();
E previous();
int nextIndex();
int previousIndex();
void remove();
void set(E e); // Replace last returned element
void add(E e); // Insert element before next()
}Example
List<String> colors = new ArrayList<>(Arrays.asList("Red", "Green", "Blue"));
ListIterator<String> lit = colors.listIterator();
// Forward traversal
while (lit.hasNext()) {
int index = lit.nextIndex();
String color = lit.next();
System.out.println(index + ": " + color);
}
// Output: 0: Red, 1: Green, 2: Blue
// Backward traversal
while (lit.hasPrevious()) {
String color = lit.previous();
System.out.println(color);
}
// Output: Blue, Green, RedModifying During Iteration
Starting from a Specific Position
// Start iteration from index 2
ListIterator<String> lit = list.listIterator(2);Iterator vs ListIterator
| Feature | Iterator | ListIterator |
|---|---|---|
| Direction | Forward only | Forward and backward |
| Available for | Any Collection | Only List |
| Methods | hasNext, next, remove | + hasPrevious, previous, set, add |
| Index access | No | nextIndex(), previousIndex() |
| Modification | remove() only | remove(), set(), add() |
The Iterable Interface
Any class implementing Iterable<T> can be used in a for-each loop:
public interface Iterable<T> {
Iterator<T> iterator();
default void forEach(Consumer<? super T> action) { ... }
default Spliterator<T> spliterator() { ... }
}Custom Iterable Example
Spliterator (Java 8+)
Spliterator (Splitable Iterator) is designed for parallel processing:
public interface Spliterator<T> {
boolean tryAdvance(Consumer<? super T> action);
Spliterator<T> trySplit(); // Split into two halves
long estimateSize();
int characteristics();
}Key Characteristics
| Characteristic | Meaning |
|---|---|
| ORDERED | Elements have a defined encounter order |
| DISTINCT | No duplicates (like Set) |
| SORTED | Elements are in sorted order |
| SIZED | estimateSize() returns exact count |
| NONNULL | No null elements |
| IMMUTABLE | Source cannot be modified |
| CONCURRENT | Source can be safely modified concurrently |
| SUBSIZED | Split children are also SIZED |
Usage with Streams
List<String> words = Arrays.asList("Hello", "World", "Java", "Streams");
Spliterator<String> spliterator = words.spliterator();
// Characteristics
System.out.println(spliterator.estimateSize()); // 4
System.out.println(spliterator.hasCharacteristics(Spliterator.ORDERED)); // true
// Split for parallel processing
Spliterator<String> secondHalf = spliterator.trySplit();
// spliterator now covers first half, secondHalf covers second halfIteration Performance
| Collection | Iterator Creation | next() | hasNext() |
|---|---|---|---|
| ----------- | :-: | :-: | :-: |
| ArrayList | O(1) | O(1) | O(1) |
| LinkedList | O(1) | O(1) | O(1) |
| HashSet | O(1) | O(1) amortized | O(1) amortized |
| TreeSet | O(log n) | O(log n) amortized | O(1) |
| HashMap (entrySet) | O(capacity) | O(1) amortized | O(1) amortized |
Note: HashSet/HashMap iterators traverse the internal bucket array, skipping empty buckets. Iteration time is proportional to capacity (not size), so keep load factor reasonable.
Common Mistakes
1. Calling next() Without hasNext()
// WRONG — may throw NoSuchElementException
while (true) {
String item = it.next(); // Crashes when exhausted
}
// CORRECT
while (it.hasNext()) {
String item = it.next();
}2. Calling next() Twice Per Iteration
// WRONG — skips elements and may crash
while (it.hasNext()) {
System.out.println(it.next());
process(it.next()); // Calls next() AGAIN!
}
// CORRECT
while (it.hasNext()) {
String item = it.next();
System.out.println(item);
process(item);
}3. Using for-each When You Need to Remove
// WRONG
for (String s : list) {
if (condition) list.remove(s); // CME!
}
// CORRECT
Iterator<String> it = list.iterator();
while (it.hasNext()) {
if (condition) it.remove();
}4. Reusing an Exhausted Iterator
Iterator<String> it = list.iterator();
while (it.hasNext()) { it.next(); } // Exhausted
// WRONG — it's already exhausted!
while (it.hasNext()) { ... } // Won't enter loop
// CORRECT — get a fresh iterator
it = list.iterator();Interview Questions
Q1: What is the difference between Iterator and Enumeration?
A: Enumeration (legacy) has hasMoreElements() and nextElement() — no remove(). Iterator is the modern replacement with remove() support and fail-fast behavior.
Q2: What is a fail-fast iterator?
A: An iterator that throws ConcurrentModificationException if the underlying collection is structurally modified during iteration (except through the iterator's own methods).
Q3: How can you remove elements during iteration?
A: Use Iterator.remove(), ListIterator.remove(), removeIf() (Java 8+), or use a fail-safe collection like CopyOnWriteArrayList.
Q4: What is the difference between Iterator and ListIterator?
A: Iterator is forward-only and works on any Collection. ListIterator supports bidirectional traversal, index queries, and add/set operations, but only works on Lists.
Q5: Can you get ConcurrentModificationException in a single-threaded program?
A: Yes! It's not about threads — it's about modifying the collection directly (not through the iterator) during iteration.
Q6: What is a Spliterator?
A: A parallel-capable iterator introduced in Java 8. It can split a data source into two halves for divide-and-conquer parallel processing in streams.
Q7: Why should you prefer Iterator over index-based loop for LinkedList?
A: Because list.get(i) on LinkedList is O(n) (traverses from head each time), making an indexed loop O(n²). Iterator traverses in O(n) total.
Q8: What is the difference between Iterator and Spliterator?
A: Iterator is sequential and single-threaded. Spliterator (Java 8+) supports parallel traversal — it can split the data source into multiple parts for parallel processing in streams. Spliterator also provides characteristics (ORDERED, SORTED, SIZED, etc.) and estimateSize() for optimization.
Q9: How does fail-fast detection work internally?
A: Collections maintain a modCount field incremented on every structural modification (add, remove). When an iterator is created, it saves the current modCount as expectedModCount. Before each next() call, it checks if modCount != expectedModCount — if true, throws ConcurrentModificationException.
Q10: What is the difference between Iterator.remove() and Collection.remove()?
A: Iterator.remove() removes the last element returned by next() and is safe to call during iteration (updates internal state). Collection.remove() during iteration triggers ConcurrentModificationException because the iterator's state becomes inconsistent with the collection.
Q11: Can you iterate a Map using Iterator?
A: Not directly — Map doesn't extend Iterable. But you can iterate its views: map.keySet().iterator(), map.values().iterator(), or map.entrySet().iterator(). The entrySet iterator gives you both keys and values via Map.Entry.
Q12: What are the limitations of for-each loop compared to Iterator?
A: For-each cannot: (1) remove elements during iteration, (2) traverse backwards (ListIterator can), (3) access the iterator index, (4) iterate multiple collections simultaneously. Use explicit Iterator when you need these capabilities.
Summary
| Concept | Key Point |
|---|---|
Iterator | Forward-only, universal, safe removal |
ListIterator | Bidirectional, list-only, full modification |
Iterable | Implement to enable for-each loop |
Spliterator | Parallel-capable splitting iterator |
| Fail-fast | Detects concurrent modification via modCount |
remove() | Only safe way to remove during iteration |
forEachRemaining() | Process remaining elements with lambda |
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for Iterator in Java.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this Java Master Course topic.
Search Terms
java-master-course, java master course, java, master, course, collections, framework, iterator
Related Java Master Course Topics