这个问题与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
也就是说,现在为完整循环执行已排序的方法,然后对各个项执行过滤和映射函数。 因为所有三个都是中间函数,所以所有都应该以相同的方式工作。 执行顺序是否正常?我不知道我做错了什么。
答案 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])
,也不保证映射器函数应用于各个元素的顺序,或者在什么线程中为给定元素执行任何行为参数。