Java流(Stream)中的sorted()行为取决于接下来的takeWhile()调用。

huangapple go评论101阅读模式
英文:

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

问题

以下是您要翻译的内容:

我正在练习流操作。然后出现了这种奇怪的行为。我无法弄清楚原因。这就是为什么要寻求帮助。

我写了这个:

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

这在控制台上什么都没有输出,这是预期的。当我在IntelliJ IDEA中查看流链时,得到了这个:

Java流(Stream)中的sorted()行为取决于接下来的takeWhile()调用。

所以,在执行了**sorted()**之后,它只向流水线返回了一个元素(图中的元素是2)。

现在我注释了**takeWhile()**的调用。像这样:

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

这次控制台上按预期输出(从10到2,间隔为2)。

但问题是,这次**sorted()**返回了5个元素到流水线。当我在IntelliJ IDEA中查看流链时,得到了这个:

Java流(Stream)中的sorted()行为取决于接下来的takeWhile()调用。

我的问题是,为什么调用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:

  1. IntStream.iterate(10, i -> i - 2)
  2. .limit(5)
  3. .sorted()
  4. .takeWhile(i -> i > 2)
  5. .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:

Java流(Stream)中的sorted()行为取决于接下来的takeWhile()调用。

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:

  1. IntStream.iterate(10, i -> i - 2)
  2. .limit(5)
  3. .sorted()
  4. // .takeWhile(i -> i > 2)
  5. .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:

Java流(Stream)中的sorted()行为取决于接下来的takeWhile()调用。

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.

huangapple
  • 本文由 发表于 2020年8月23日 19:48:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/63546583.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定