⚡IntermediateCollections Framework

Iterator and ListIterator

Traverse and safely modify collections during iteration using Iterator and ListIterator.

Overview

Every collection in Java provides an iterator via the iterator() method. An Iterator lets you traverse the collection one element at a time, and safely remove elements during traversal without throwing ConcurrentModificationException. ListIterator extends Iterator with bidirectional traversal and add/set support, but only works on List implementations. The for-each loop is syntax sugar over Iterator. When you need to remove elements while looping, or traverse backwards, use the explicit Iterator instead.

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.

Loading editor…

Completed: 0 / 4 exercises

Knowledge Check

Question 1 of 4

Why should you use Iterator.remove() instead of List.remove() while iterating?