Java 8 Stream - 排序方法的执行标准与filter和map方法的工作方式不同

时间:2016-11-29 11:10:11

标签: java filter java-8 stream java-stream

这个问题与Java 8 Stream - Filter and foreach method not printing as expected

有关

我正在使用Java 8 Stream的sorted,filter和map方法。 请记住过滤器和地图如何按照上述问题的答案中的规定工作,我尝试了如下排序方法:

var array = [
    { "name": "Joe", "age": 17 },
    { "name": "Bob", "age": 17 },
    { "name": "Carl", "age": 35 }
];

_.chain(array).map('age').unique().value();

我得到的输出是:

  

排序:a2; D2   排序:b1; a2   排序:b1; D2   排序:b1; a2   排序:b3; B1   排序:b3; D2   排序:c; B3   排序:c; D2   过滤器:a2   地图:a2   forEach:A2   过滤器:b1   过滤器:b3   过滤器:c   过滤器:d2

也就是说,现在为完整循环执行已排序的方法,然后对各个项执行过滤和映射函数。 因为所有三个都是中间函数,所以所有都应该以相同的方式工作。 执行顺序是否正常?我不知道我做错了什么。

2 个答案:

答案 0 :(得分:3)

“这取决于”。流操作可以交错,因为每个阶段一旦订单明显就可以发出项目。在过滤和映射的情况下,每个项目都可以被处理和吞下或传递。

在排序的情况下,这一切都取决于排序算法。如果排序实现为“找到具有n-1个比较的所有元素的最小值,发出最小值,重复其余”,则排序确实会与过滤和映射交错。但是看看你的输出,它看起来更像是插入排序(使用二进制搜索或插入点的一些搜索树):a2 / d2被比较得到(a2,d2);首先将b1与a2进行比较,然后将d2与两个屈服点(a2,b1,d2)进行比较,将b3与b1进行比较,然后将d2与(a2,b1,b3,d2)进行比较,依此类推。 这是有道理的,因为它产生预期的O(nlogn)排序时间(与重复的最小发现的O(n ^ 2)相比),但是在插入最后一个元素之前它不能发出任何东西。 也就是说,必须在过滤开始之前完成排序。

答案 1 :(得分:3)

https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html

  

<强>副作用

     

通常不鼓励对流操作的行为参数产生副作用,因为它们通常会导致无意中违反无国籍要求以及其他线程安全隐患。

     

[...]此外,这些效果的排序可能会令人惊讶。即使管道被约束以产生与流源的遭遇顺序一致的结果(例如,IntStream.range(0,5).parallel().map(x -> x*2).toArray() must produce [0, 2, 4, 6, 8]),也不保证映射器函数应用于各个元素的顺序,或者在什么线程中为给定元素执行任何行为参数。

enter image description here