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 bynext(). Must be called only afternext(); otherwise, it throwsIllegalStateException.
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.