Iterator and ListIterator
Traverse and safely modify collections during iteration using Iterator and ListIterator.
Overview
Key Points
- •iterator() returns an Iterator<E> for any Collection
- •hasNext() returns true if more elements remain
- •next() returns the next element and advances the cursor
- •remove() deletes the last element returned by next(), safe during iteration
- •for-each is syntactic sugar over iterator; you cannot call remove() through it
- •listIterator() returns a ListIterator that can go forward and backward
- •ListIterator.add(e) inserts before the cursor position
- •ListIterator.set(e) replaces the last element returned by next() or previous()
Examples
Safe removal during iteration
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<String> words = new ArrayList<>(
List.of("keep", "DELETE", "keep", "DELETE", "keep")
);
Iterator<String> it = words.iterator();
while (it.hasNext()) {
String word = it.next();
if (word.equals("DELETE")) {
it.remove(); // safe removal during iteration
}
}
System.out.println(words); // [keep, keep, keep]
}
}Never call list.remove(element) directly inside a for-each loop. Use the iterator's remove() method instead.
Iterating manually
import java.util.Iterator;
import java.util.Set;
import java.util.HashSet;
public class Main {
public static void main(String[] args) {
Set<Integer> numbers = new HashSet<>(Set.of(10, 20, 30, 40, 50));
Iterator<Integer> it = numbers.iterator();
while (it.hasNext()) {
int n = it.next();
System.out.print(n + " ");
}
System.out.println();
// Remove elements divisible by 20
it = numbers.iterator();
while (it.hasNext()) {
if (it.next() % 20 == 0) it.remove();
}
System.out.println("After removal: " + numbers);
}
}Iterator works on any Collection, including Set, which has no index-based remove.
ListIterator: bidirectional and edit
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
public class Main {
public static void main(String[] args) {
List<String> items = new ArrayList<>(List.of("a", "b", "c", "d"));
ListIterator<String> lit = items.listIterator();
// Forward pass: uppercase each element
while (lit.hasNext()) {
String s = lit.next();
lit.set(s.toUpperCase()); // replace in place
}
System.out.println("Uppercased: " + items); // [A, B, C, D]
// Backward pass
System.out.print("Reverse: ");
while (lit.hasPrevious()) {
System.out.print(lit.previous() + " ");
}
System.out.println();
}
}After a full forward pass, the ListIterator cursor is at the end, so hasPrevious() is immediately true for a backward pass.
Common Mistakes
- Calling next() when hasNext() is false throws NoSuchElementException. Always check hasNext() first
- Calling iterator.remove() without a preceding next() call throws IllegalStateException
- Assuming the iteration order of a HashSet is consistent across runs. It is not guaranteed
Note
For simple filtering during iteration, prefer list.removeIf(predicate) introduced in Java 8. It is shorter and more readable than the explicit Iterator pattern.
Exercises
Write Java code and click Run to execute it instantly. When your output looks correct, mark as done.
Completed: 0 / 4 exercises
Knowledge Check
Question 1 of 4