Home/Learn/Java A–Z/Iterator & Iterable

Iterator & Iterable

Intermediate
Streams & Functional Java

Implement Iterable to enable enhanced for-each on your own classes, understand Iterator fail-fast behaviour, and use ListIterator for bidirectional traversal.

Overview

The Iterator pattern decouples traversal logic from the collection. Iterable<T> has one method: iterator(), which returns an Iterator<T>. Iterator<T> has hasNext(), next(), and optional remove(). Implementing Iterable on your class enables enhanced for-each syntax. Java's collection iterators are fail-fast — they throw ConcurrentModificationException if the collection is structurally modified during iteration (via any means other than the iterator's own remove).

Iterator & Iterable Contracts

Iterator contract: • hasNext() — returns true if more elements remain • next() — returns the next element, throws NoSuchElementException if none • remove() — optional; removes the last element returned by next()

Iterable contract: implement iterator() to return a fresh Iterator each time.

Range.java
import java.util.Iterator;
import java.util.NoSuchElementException;

// Custom range that is Iterable — enables for-each
public class Range implements Iterable<Integer> {
    private final int start;
    private final int end;   // exclusive

    public Range(int start, int end) {
        this.start = start;
        this.end   = end;
    }

    @Override
    public Iterator<Integer> iterator() {
        return new Iterator<>() {
            private int current = start;

            @Override public boolean hasNext() { return current < end; }

            @Override public Integer next() {
                if (!hasNext()) throw new NoSuchElementException();
                return current++;
            }
            // remove() not supported — default throws UnsupportedOperationException
        };
    }

    public static void main(String[] args) {
        Range range = new Range(1, 6);

        // Enhanced for-each — works because Range is Iterable
        for (int n : range) System.out.print(n + " "); // 1 2 3 4 5
        System.out.println();

        // Explicit iterator usage
        Iterator<Integer> it = range.iterator();
        while (it.hasNext()) System.out.print(it.next() + " ");
        System.out.println();

        // Stream from Iterable (via StreamSupport)
        import java.util.stream.StreamSupport;
        StreamSupport.stream(range.spliterator(), false)
            .filter(n -> n % 2 == 0)
            .forEach(System.out::print); // 2 4
    }
}

Fail-Fast & Safe Removal

ArrayList, HashMap, HashSet iterators are fail-fast — they track modCount and throw ConcurrentModificationException if you structurally modify the collection outside the iterator during iteration. Always use Iterator.remove() or Collection.removeIf() for safe in-loop removal.

IteratorSafety.java
import java.util.*;

public class IteratorSafety {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>(List.of(1, 2, 3, 4, 5, 6));

        // WRONG: remove() via list during for-each — throws CME
        try {
            for (Integer n : list) {
                if (n % 2 == 0) list.remove(n); // structural modification!
            }
        } catch (ConcurrentModificationException e) {
            System.out.println("CME caught");
        }

        // CORRECT 1: Iterator.remove()
        Iterator<Integer> it = list.iterator();
        while (it.hasNext()) {
            if (it.next() % 2 == 0) it.remove(); // safe
        }
        System.out.println(list); // [1, 3, 5]

        // CORRECT 2: removeIf (cleanest)
        list = new ArrayList<>(List.of(1, 2, 3, 4, 5, 6));
        list.removeIf(n -> n % 2 == 0);
        System.out.println(list); // [1, 3, 5]

        // Map iteration
        Map<String, Integer> map = new HashMap<>(Map.of("a",1,"b",2,"c",3));
        map.entrySet().removeIf(e -> e.getValue() < 2); // safe bulk removal
        System.out.println(map); // {b=2, c=3}
    }
}

ListIterator — Bidirectional Traversal

ListIterator extends Iterator and adds hasPrevious(), previous(), nextIndex(), previousIndex(), add(), and set(). It allows traversal in both directions and mutation during iteration — essential for efficient in-place modification of a LinkedList.

ListIteratorDemo.java
import java.util.*;

public class ListIteratorDemo {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>(List.of("a","b","c","d","e"));

        // ListIterator — bidirectional
        ListIterator<String> lit = list.listIterator(list.size()); // start at end
        System.out.print("Reverse: ");
        while (lit.hasPrevious()) System.out.print(lit.previous() + " ");
        System.out.println(); // e d c b a

        // set() — replace last returned element
        ListIterator<String> it2 = list.listIterator();
        while (it2.hasNext()) {
            String s = it2.next();
            it2.set(s.toUpperCase()); // replace in-place
        }
        System.out.println(list); // [A, B, C, D, E]

        // add() — insert at current position
        ListIterator<String> it3 = list.listIterator();
        it3.next();          // moves past A
        it3.add("A+");       // inserts after A
        System.out.println(list); // [A, A+, B, C, D, E]
    }
}

Key Points to Remember

  • Implement Iterable<T> with iterator() to enable enhanced for-each on custom classes
  • Iterator.remove() is the only safe way to remove during iteration — do not use collection.remove() in a loop
  • removeIf(Predicate) is the cleanest bulk-removal approach — no CME risk
  • Fail-fast iterators throw ConcurrentModificationException on concurrent structural modification
  • ListIterator supports bidirectional traversal, set() and add() during iteration
  • StreamSupport.stream(iterable.spliterator(), parallel) converts any Iterable to a Stream

Practice Iterator & Iterable in the Playground

Run and modify code directly in your browser - no setup needed.

Interview Questions

Sign in to ask Aria
1

What is the difference between Iterable and Iterator?

EasyTCS
2

What is a fail-fast iterator? How do you avoid ConcurrentModificationException?

MediumAmazon
3

How do you safely remove elements from a list while iterating?

EasyGoogle
4

What is the difference between Iterator and ListIterator?

MediumOracle
5

How do you implement Iterable on a custom class?

MediumMicrosoft

Ask Aria about Iterator & Iterable

Your personal AI tutor — ask anything about this concept