Understanding Iterable and Iterator in Java Collections

To enable iteration over a collection using enhanced for-loops, a class must implement the Iterable interface. This contract requires providing an Iterator instance via the iterator() method — essentially granting permission to be traversed element by element.

// Minimal Iterable interface
public interface Iterable<T> {
    Iterator<T> iterator();
}

The returned Iterator governs traversal through three core operations:

  • hasNext(): Checks if more elements remain for iteration.
  • next(): Returns the current element and advances the internal pointer.
  • remove(): Deletes the last element returned by next(). Must be called only after next(); otherwise, it throws IllegalStateException.
public interface Iterator<E> {
    boolean hasNext();
    E next();

    // Optional removal operation (default implementation throws exception)
    default void remove() {
        throw new UnsupportedOperationException("remove");
    }
}

The default keyword (introduced in Java 8) allows interfaces to provide concrete method implementations without forcing all implementing classes to override them — enabling backward-compatible API evolution.

Why Separate Iterable from Iterator?

Collections like List or Set implement Iterable, not Iterator directly. This design avoids embedding iteration state (like cursor position) into the collection itself. If they implemented Iterator, concurrent or nested iterations would interfere with each other due to shared state. Instead, each call to iterator() returns a fresh, independent iterator — supporting safe parallel traversals.

Menual Iteration Example

Enhanced for-loops internally use iterators. However, to safely remove elements during traversal, manual iteration is required:

List<String> words = Arrays.asList("apple", "banana", "cherry");
Iterator<String> walker = words.iterator();

while (walker.hasNext()) {
    String item = walker.next();
    if ("banana".equals(item)) {
        walker.remove(); // Safe removal during iteration
    }
}

Custom Iteratro Implementation Pattern

While rarely neeeded outside framework development, here’s a simplified version inspired by AbstractList.Itr:

private class ElementWalker implements Iterator<T> {
    private int currentIndex = 0;
    private int lastVisitedIndex = -1;

    public boolean hasNext() {
        return currentIndex < totalSize();
    }

    public T next() {
        if (!hasNext()) throw new NoSuchElementException();
        T value = fetchElement(currentIndex);
        lastVisitedIndex = currentIndex++;
        return value;
    }

    public void remove() {
        if (lastVisitedIndex == -1) 
            throw new IllegalStateException("next() not called before remove()");
        
        discardElement(lastVisitedIndex);
        if (lastVisitedIndex < currentIndex) currentIndex--;
        lastVisitedIndex = -1;
    }
}

This pattern ensures thread-local iteration state and safe element removal without corrupting the traversal process.

Tags: java iterable iterator Collections java8

Posted on Tue, 14 Jul 2026 16:34:12 +0000 by Dragen