Iterator and Iterable

Basic Java
≈ 2 min read

An object that moves through a collection

Iterator<E> represents sequential traversal of elements. It keeps the current position and answers two main questions: is there another element, and which element should be returned next?

List<String> names = List.of("Ann", "Bob", "Cara");
Iterator<String> iterator = names.iterator();

while (iterator.hasNext()) {
    String name = iterator.next();
    System.out.println(name);
}

hasNext() checks whether any elements remain, and next() returns the next one and advances the iterator. Calling next() after the end of the sequence causes an exception.

Iterable makes an object traversable

The Iterable<T> interface requires an iterator() method. That is what allows an object to be used in a for-each loop. Most collections implement Iterable through their hierarchy.

for (String name : names) {
    System.out.println(name);
}

This loop is shorter than working with an iterator manually, but the idea underneath is the same: obtain a traversal object and request elements one by one.

Safe removal during traversal

Ordinary modification of the collection from somewhere else while iterating can disrupt the traversal. If you need to remove the current element, the iterator-supported approach is to use its remove() after next().

List<String> values = new ArrayList<>(List.of("keep", "remove", "keep"));
Iterator<String> it = values.iterator();

while (it.hasNext()) {
    if (it.next().equals("remove")) {
        it.remove();
    }
}
Do not mix two ways of modifying the same collection during traversal. If traversal is happening through an iterator, remove the current element through that iterator as well, when the particular implementation supports the operation.