Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java stream sorted() behavior is depending on next takeWhile() calling

I was practicing stream. Then got this strange behavior. I can't figure out the reason. That's why asking for help.

I wrote this:

IntStream.iterate(10, i -> i - 2)
            .limit(5)
            .sorted()
            .takeWhile(i -> i > 2)
            .forEach(System.out::println);

This is giving me nothing in the console, which is expected. When I am seeing the stream chain in IntelliJ IDEA, getting this:

enter image description here

So, after the execution of sorted() it is returning only one element (that element is 2 in the image) to the pipeline.

Now I commented the takeWhile() call. Like this:

IntStream.iterate(10, i -> i - 2)
            .limit(5)
            .sorted()
        //    .takeWhile(i -> i > 2)
            .forEach(System.out::println);

This is also printing in the console as expected(from 10 to 2 with a difference of 2).

But problem is, this time sorted() returned 5 elements to pipeline. When I am seeing the stream chain in IntelliJ IDEA, getting this:

enter image description here

My question is, why the difference is seen in calling sorted()? If there is a takeWhile() after sorted() then it is returning one element. If I am commenting takeWhile(), sorted() is returning stream of 5 elements.

Is JVM doing anything here for achieving better performance?

Thanks in advance.....

like image 933
Mukit09 Avatar asked Jan 24 '23 19:01

Mukit09


1 Answers

Stream.sorted() is a stateful operation, so it is actually maintaining the [2, 4, 6, 8, 10] state. However, it will only send 1 item at a time.

So, Initially it will send 1 entry: '2' to takeWhile operator which can then reject the entry and stop the stream chain. That is why you are seeing sorted returning only 2 to takeWhile operator.

But, when sorted is not present, takeWhile will get 10 as the entry. And as the condition is true, stream will continue until takeWhile receives 2.

Edit: When takeWhile is not present, you are getting all 5 items as output because you have 5 items in stream chain and there is no takeWhile to stop the stream chain.

In Intellij's Stream Trace, On the right side of sorted you are seeing how many elements are being passed to next operator after performing sorted() operation.

In the first case, only 1 element is being passed to takeWhile() as takeWhile() is terminating the stream chain after receiving '2'. But in the second case all the elements are being passed to forEach.

like image 153
THe_strOX Avatar answered Feb 05 '23 16:02

THe_strOX