在java 8文档(doc order stream)中,可以看到:
如果[stream]没有被排序,重复执行可能会产生不同 结果
我的问题很简单:是否有一种简单的方法可以在一个小单元测试中说明这个事实(可能使用HashMap或类似的东西)?
[编辑]整个报价在这里:
对于顺序流,遇到顺序的存在与否不会影响性能,只影响确定性。如果订购了流,则在相同的源上重复执行相同的流管道将产生相同的结果;如果没有订购,重复执行可能会产生不同的结果。
因此,我的问题是关于严格顺序而不是平行的执行。在这种情况下,我一直在质疑。
答案 0 :(得分:3)
显而易见的答案是,无论何时使用unordered
,都应该得到不同的结果。例如使用这个:
int first = Arrays.asList(1, 2, 3, 4).stream()
.unordered()
.parallel()
.findFirst()
.get();
System.out.println(first);
应该产生 not 始终为1的结果。因为流是无序的,所以[1,2,3,4]
之外的任何结果都是可能的。
在java-8中,这不是真的,流管道不会考虑unordered
:
@Override
public <P_IN> O evaluateParallel(PipelineHelper<T> helper,
Spliterator<P_IN> spliterator) {
return new FindTask<>(this, helper, spliterator).invoke();
}
但是java-9中的情况发生了变化:
@Override
public <P_IN> O evaluateParallel(PipelineHelper<T> helper,
Spliterator<P_IN> spliterator) {
// This takes into account the upstream ops flags and the terminal
// op flags and therefore takes into account findFirst or findAny
boolean mustFindFirst = StreamOpFlag.ORDERED.isKnown(helper.getStreamAndOpFlags());
return new FindTask<>(this, mustFindFirst, helper, spliterator).invoke();
}
因此,在java-9下多次运行相同的代码会产生不同的结果。
有一些操作已经unordered
Stream#generate
和Stream#forEach
。
答案 1 :(得分:2)
Stream#forEach的文档已经说明如下:
此操作的行为明确为 nondeterministic 。对于并行流管道,此操作不保证尊重流的遭遇顺序,因为这样做会牺牲并行性的好处。
所以应该通过以下测试:
List<Integer> ordered = Arrays.asList(1, 2, 3, 4);
List<Integer> unordered = new CopyOnWriteArrayList<>();
ordered.stream().parallel().forEach(unordered::add);
assertThat(unordered, not(equalTo(ordered)));
并且操作Stream#findAny也是不确定。