Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java 8 stream peek and limit interaction

Why this code in java 8:

IntStream.range(0, 10)
        .peek(System.out::print)
        .limit(3)
        .count();

outputs:

012

I'd expect it to output 0123456789, because peek preceeds limit.

It seems to me even more peculiar because of the fact that this:

IntStream.range(0, 10)
        .peek(System.out::print)
        .map(x -> x * 2)
        .count();

outputs 0123456789 as expected (not 02481012141618).

P.S.: .count() here is used just to consume stream, it can be replaced with anything else

like image 650
tsds Avatar asked Sep 26 '14 11:09

tsds


People also ask

What is peek in Java 8 stream?

Java 8. Java Stream Basics, Java Stream Methods. Java Stream peek() method returns a new Stream consisting of all the elements from the original Stream after applying a given Consumer action.

Does Java 8 streams have limited storage?

No storage. Streams don't have storage for values; they carry values from a source (which could be a data structure, a generating function, an I/O channel, etc) through a pipeline of computational steps.

Why would you choose to use a peek operation instead of a forEach operation on a stream?

peek can get the smallest item directly compared with stream. foreach().

What does the method stream T peek consumer <? Super T action describe?

In Java, Stream provides an powerful alternative to process data where here we will be discussing one of the very frequently used methods named peek() which being a consumer action basically returns a stream consisting of the elements of this stream, additionally performing the provided action on each element as ...


2 Answers

The most important thing to know about streams are that they do not contain elements themselves (like collections) but are working like a pipe whose values are lazily evaluated. That means that the statements that build up a stream - including mapping, filtering, or whatever - are not evaluated until the terminal operation runs.

In your first example, the stream tries to count from 0 to 9, one at each time doing the following:

  1. print out the value
  2. check whether 3 values are passed (if yes, terminate)

So you really get the output 012.

In your second example, the stream again counts from 0 to 9, one at each time doing the following:

  1. print out the value
  2. maping x to x*2, thus forwarding the double of the value to the next step

As you can see the output comes before the mapping and thus you get the result 0123456789. Try to switch the peek and the map calls. Then you will get your expected output.

like image 140
Seelenvirtuose Avatar answered Oct 20 '22 00:10

Seelenvirtuose


From the docs:

limit() is a short-circuiting stateful intermediate operation.

map() is an intermediate operation

Again from the docs what that essentially means is that limit() will return a stream with x values from the stream it received.

An intermediate operation is short-circuiting if, when presented with infinite input, it may produce a finite stream as a result.

like image 36
Sourav 'Abhi' Mitra Avatar answered Oct 19 '22 23:10

Sourav 'Abhi' Mitra