MsA
MsA

Reputation: 2979

Understanding java Stream.limit() operation

I was learning Stream.limit() says:

Returns a stream consisting of the elements of this stream, truncated to be no longer than maxSize in length.

This can be understood from:

Stream.of(1,2,3,4,5,6,7,8)
    .limit(3)
    .forEach(i -> {
        System.out.print(i + ",");
    });  //prints: 1,2,3,

However when used with other stream methods, it has an effect of processing elements in batch:

Stream.of(1,2,3,4,5,6,7)
    .filter(i -> {
        System.out.println("Filtering "  + i + ": " + (i%2 == 0));
        return i%2 == 0;
    })
    .map(i-> {
        System.out.println("Mapping " + i + " to " + i*i);
        return i*i;
    })
    .limit(2)
    .forEach(i -> System.out.println("---> " + i));

Prints:

Filtering 1: false
Filtering 2: true
Mapping 2 to 4
---> 4
Filtering 3: false
Filtering 4: true
Mapping 4 to 16
---> 16

Here, you can see elements are processed in batch of 2.

I have following doubts:

  1. Why it did not processed only first two elements 1 and 2? That is, why the output is not just:

     Filtering 1: false
     Filtering 2: true
     Mapping 2 to 4
     ---> 4
    
  2. Why it did not processed last four elements 5,6,7 and 8 and printed following?:

     Filtering 5: false
     Filtering 6: true
     Mapping 6 to 36
     ---> 36
     Filtering 7: false
     Filtering 8: true
     Mapping 8 to 64
     ---> 64
    

Upvotes: 3

Views: 2623

Answers (1)

Karol Dowbecki
Karol Dowbecki

Reputation: 44952

  1. Both 1 and 2 were processed. 1 is odd so the filter removes it from the stream pipeline. 2 is even and went through entire stream pipeline resulting in 4 being printed out in forEach.

  2. Streams are lazy in nature. Since you used limit(2) only two elements will make it through the limit pipeline step. 2 and 4 went through entire stream pipeline resulting in 4 and 16 being printed out in forEach.

limit() is a short-circuiting stateful intermediate operation, as per docs:

Short-circuiting operations such as limit(n) or findFirst() can allow computations on infinite streams to complete in finite time.

...

Further, some operations are deemed short-circuiting operations. An intermediate operation is short-circuiting if, when presented with infinite input, it may produce a finite stream as a result. A terminal operation is short-circuiting if, when presented with infinite input, it may terminate in finite time. Having a short-circuiting operation in the pipeline is a necessary, but not sufficient, condition for the processing of an infinite stream to terminate normally in finite time.

Upvotes: 5

Related Questions