Can we consider that the .stream()
call on a Collection create some sort of an iterator?
Yes we can! But the interesting question is, what sort of an iterator is it? The Iterator Design Pattern was originally published in the GoF book. On page 260 it states,
Iterator has many implementation variants and alternatives.
We might not recognize a stream as an iterator, because (in Java) we are so used to seeing the version of the pattern where the client explicitly calls next()
and hasNext()
. Streams are clearly not that version of the Iterator pattern, so what are they?
Who controls the iteration? A fundamental issue is deciding which party controls the iteration, the iterator or the client that uses the iterator. When the client controls the iteration, the iterator is called an external iterator, and when the iterator controls it, the iterator is an internal iterator. Clients that use an external iterator must advance the traversal and request the next element explicitly from the iterator. In contrast, the client hands an internal iterator an operation to perform, and the iterator applies that operation to every element in the aggregate.
There can be no doubt the Java Stream API was designed with the Iterator pattern in mind, and particularly the internal version of the pattern, because Stuart Marks and Brian Goetz have both graciously posted about their design decisions, here on SO. Stuart mentions how the initial prototype was based on Iterable
itself. That was insufficient for parallel processing, and Brian describes how the ultimate implementation of the Stream API is now based on Spliterator
.
So a Stream
is still an iterator, but an internal iterator as opposed to the older Java APIs like Iterator
and Enumeration
.