peek().iterator().hasNext() pre-consumes elements?

Brian Goetz brian.goetz at
Tue Feb 12 10:16:25 PST 2013

The answer here is complicated, but in general, calling hasNext may well 
require consuming an element -- there's often no way to know whether a 
source would produce an element without asking it to do so.  So it is a 
common practice in implementing iterators to do this (one of many 
reasons why we did not build Streams on Iterator.)

Because the elements are coming from an array, it might be possible to 
know simply based on how many elements have gone by that the stream is 
not yet exhausted.  But in the general case (such as when the stream 
source is an IO channel), it is not possible to know without actually 
consuming and buffering some input.  So I would put this in the category 
of "acceptable" behavior.  We might someday do some work to take 
advantage of the fact that the source has the SIZED characteristic and 
the pipeline stages are size-preserving to make this case behave 
"better", but that would be an implementation quality issue, not a spec 
issue.  The behavior you observe is allowable by the spec.

On 2/12/2013 12:53 PM, Dmitry Bessonov wrote:
> Hello,
> The following line prints out the first element, "1"
>     Arrays.asList(1, 2,
> 3).stream().peek(System.err::println).iterator().hasNext()
> Is it really an expected behavior?
> -Dmitry

More information about the lambda-dev mailing list