无序和并行时的Java流限制和跳过行为

时间:2016-01-22 11:45:39

标签: java parallel-processing java-8 java-stream

所以我一直在玩并行运行流,并根据API文档和我读过的其他支持材料监控它们的行为。

我创建了两个并行流并运行distinct(),一个是流的顺序,一个是无序的。然后,我使用forEachOrdered()打印结果(以确保在不同运行后我看到流的结果遇到顺序),并且可以清楚地看到无序版本不维护原始排序,但是使用大型数据集,显然会提高并行性能。

有一些API说明表明,当流无序时,limit()skip()操作也应该更有效地并行运行,而不必检索第一个n元素,可以获得任何n个元素。我试图以与上面相同的方式模拟这个,但是当与有序和无序流并行运行时的结果总是相同的。换句话说,当我在运行限制后打印出结果时,即使对于无序(并行)流,它仍然总是选择前n个元素?

任何人都能解释一下吗?我尝试改变输入数据集的大小和n的值,它没有任何区别。我本以为它会抓住任何n个元素并优化并行性能?有没有人真正看到过这种情况在实践中发生,并且可能提供一种能够始终如一地展示这种行为的解决方案?

1 个答案:

答案 0 :(得分:4)

您可能尝试从SIZED / SUBSIZED源创建流(例如arrayList.stream()Arrays.stream(array)IntStream.range()等)并立即发出limit或{{1操作。这种情况在skip / limit实现中特别优化(参见SliceOps),并且对于有序和无序流以相同的速度运行(实际上运行速度非常快)。如果删除这些特征(例如,添加过滤步骤),您将看到在此之后使流无序有效。像这样写测试:

skip

或者,您可以使用非SUBSIZED来源进行测试(例如,input.stream().parallel().filter(x -> true).skip(..)... input.stream().parallel().unordered().filter(x -> true).skip(..)... input.stream().parallel().filter(x -> true).limit(..)... input.stream().parallel().unordered().filter(x -> true).limit(..)... TreeSet)。