搜索java-8流不一致行为的例子?

时间:2017-07-06 09:28:45

标签: lambda java-8 hashmap java-stream

在java 8文档(doc order stream)中,可以看到:

  

如果[stream]没有被排序,重复执行可能会产生不同   结果

我的问题很简单:是否有一种简单的方法可以在一个小单元测试中说明这个事实(可能使用HashMap或类似的东西)?

[编辑]整个报价在这里:

  

对于顺序流,遇到顺序的存在与否不会影响性能,只影响确定性。如果订购了流,则在相同的源上重复执行相同的流管道将产生相同的结果;如果没有订购,重复执行可能会产生不同的结果。

因此,我的问题是关于严格顺序而不是平行的执行。在这种情况下,我一直在质疑。

2 个答案:

答案 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#generateStream#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也是不确定