英文:
Java stream sorted() behavior is depending on next takeWhile() calling
问题
以下是您要翻译的内容:
我正在练习流操作。然后出现了这种奇怪的行为。我无法弄清楚原因。这就是为什么要寻求帮助。
我写了这个:
IntStream.iterate(10, i -> i - 2)
.limit(5)
.sorted()
.takeWhile(i -> i > 2)
.forEach(System.out::println);
这在控制台上什么都没有输出,这是预期的。当我在IntelliJ IDEA中查看流链时,得到了这个:
所以,在执行了**sorted()**之后,它只向流水线返回了一个元素(图中的元素是2)。
现在我注释了**takeWhile()**的调用。像这样:
IntStream.iterate(10, i -> i - 2)
.limit(5)
.sorted()
// .takeWhile(i -> i > 2)
.forEach(System.out::println);
这次控制台上按预期输出(从10到2,间隔为2)。
但问题是,这次**sorted()**返回了5个元素到流水线。当我在IntelliJ IDEA中查看流链时,得到了这个:
我的问题是,为什么调用sorted()会出现差异?如果在sorted()之后有一个takeWhile(),它只返回一个元素。如果我注释掉takeWhile(),**sorted()**就会返回包含5个元素的流。
JVM在这里做了什么以实现更好的性能吗?
提前感谢。
英文:
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:
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:
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.....
答案1
得分: 8
Stream.sorted()
是一个有状态的操作,因此实际上它在维护 [2, 4, 6, 8, 10]
状态。然而,它每次只发送一个项目。
所以,最初它会发送一个条目:'2'
给 takeWhile
操作符,然后该操作符可以拒绝该条目并停止流链。这就是为什么你只看到 sorted
返回给 takeWhile
操作符的是 2
。
但是,当没有 sorted
存在时,takeWhile
将会得到 10
作为输入。由于条件为真,流将继续直到 takeWhile
收到 2
为止。
编辑:
当没有 takeWhile
存在时,你会得到所有 5 个项目作为输出,因为你在流链中有 5 个项目,没有 takeWhile
来停止流链。
在Intellij的Stream跟踪中,在执行 sorted()
操作后,你可以在 sorted 的右侧看到有多少个元素传递给下一个操作符。
在第一种情况下,只有一个元素被传递给 takeWhile()
,因为 takeWhile()
在收到 '2'
后终止了流链。但在第二种情况下,所有元素都被传递给 forEach
。
英文:
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
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论