The iterator pattern is one of approaches to access elements of a collection, alongside with streams. From a technical point of view, the iterator traverses elements in a sequential and predictable order. In Java the behavior of iterators is defined in java.util.Iterator
contract, which is a member of Java Collections Framework.
Iterators are similar to enumerators, but there are differences between these concepts too. The enumerator provides indirect and iterative access to each element of a data structure exactly once. From the other side, iterators does the same task, but the traversal order is predictable. With this abstraction a caller can work with collection elements, without a direct access to them. Also, iterators allow to delete values from a collection during the iteration.

Do you want to increase your Java collections skills?
This topic is really huge, and a single post is not enough to cover all. That is why I wrote this Practical Guide. Everything you need in the one book. Do you want to become Java ninja?
Access elements of a collection
As it was mentioned before, the order of accessing elements is predictable, which means that the iterator traverses elements sequentially. Therefore, the general Java contract does not allow to access the particular element (however, that is possible using Commons Collections, even this violates the idea). In order to access the next element, use next()
method. It returns an element or throws NoSuchElementException
, when the iterator does not contain more elements.
In order to prevent this unchecked exception, you should call the hasNext()
method prior to accessing an element.
List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6); Iterator<Integer> iterator = numbers.iterator(); while (iterator.hasNext()) { int x = iterator.next() * 2; System.out.println(x); }
This code snippet demonstrates the usage of the iterator for sequential retrieving of elements and the printing of double value of each element.

The important thing to note here, is that once elements are consumed, the iterator can not be used. That means, that calling the iterator after traversing will lead to an error:
List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6); Iterator<Integer> iterator = numbers.iterator(); while (iterator.hasNext()) { int x = iterator.next() * 2; System.out.println(x); } int value = iterator.next();
The execution of the above code snippet will lead to the following result:

I already mentioned Apache Commons Collections. This library contains a helper class IteratorUtils
, which has a number of static utility methods to work with iterators. While some of them violate the core pattern, they can be useful. So, alongside with a sequential access, it possible to access a particular element by its index, as well there is a wrapper method to get the first element.
List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6); Iterator<Integer> iterator = numbers.iterator(); int first = IteratorUtils.first(iterator); Assertions.assertThat(first).isEqualTo(1);
Consume an element
Since Java 8 iterators permit also to specify a consumer function, which can be performed on each element. This is a shortcut of what we can do using a while block. Let consider the first example implemented with the forEachRemaining()
method. Take a look on the code snippet below:
List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6); Iterator<Integer> iterator = numbers.iterator(); iterator.forEachRemaining(number -> System.out.printf("This is a consumer. Value: %d \n", number*2));
This program listing produces the following result:

It is possible to perform such behavior with IteratorUtils. It has two static methods:
forEach()
= applies the function to each element of the provided iterator.forEachButLast()
= executes the defined function on each but the last element in the iterator
Both methods accept two arguments: an iterator instance and a closure function. The closure defines a block of code which is executed from inside some block, function or iteration. Technically, it is a same thing as a consumer functional interface. The example of using this helper method is below:
List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6); Iterator<Integer> iterator = numbers.iterator(); IteratorUtils.forEach(iterator, number -> System.out.printf("This is a closure. Value: %d \n", number*2));
The output of this snippet is:

Remove elements
Finally, we need to observe how to use an iterator to delete elements. The java.util.Iterator
interface defines the remove()
method. It deletes from the underlying collection the last element returned by the iterator. This method can be called only once per call of the next()
function. Note, that this operation is optional.
List<Integer> numbers = new ArrayList<>(); numbers.add(1); numbers.add(2); numbers.add(3); numbers.add(4); numbers.add(5); System.out.println("Initial list: "); numbers.stream().forEach(System.out::println); Iterator<Integer> iterator = numbers.iterator(); while(iterator.hasNext()) { iterator.next(); iterator.remove(); } System.out.println("Modified list: "); numbers.stream().forEach(System.out::println);
This code snippet executes and prints elements of the array list before and after removing elements, like it is presented on the screenshot below:

There are things to remember, when you use iterator.remove()
:
- As this operation is optional, it can throw the
UnsupportedOperationException
, if a collection does not have an implementation of this method (that is why I used an array list and not a generic list) - You must call the
next()
method BEFORE calling theremove()
method, otherwise it will lead to theIllegalStateException
to be thrown
That is how you can utilize an iterator in order to access elements of a collection, to perform an action on each element or to remove elements. If you have questions regarding the topic of this post, contact me using these ways.