search for example of inconsistent behavior java-8 stream?

前端 未结 2 1278
梦如初夏
梦如初夏 2020-12-06 22:28

In java 8 documentation (doc order stream), one can see this :

if [a stream] is not ordered, repeated execution might produce different results.

相关标签:
2条回答
  • 2020-12-06 23:06

    The obvious answer is that whenever you use unordered you should get different results. For example using this:

    int first = Arrays.asList(1, 2, 3, 4).stream()
               .unordered()
               .parallel()
               .findFirst()
               .get();
    System.out.println(first);
    

    should produce a result that is not always 1. Because the stream is unordered, so any result out of [1,2,3,4] is possible.

    In java-8 this is not true, the stream pipeline does not take that unordered into account:

        @Override
        public <P_IN> O evaluateParallel(PipelineHelper<T> helper,
                                         Spliterator<P_IN> spliterator) {
            return new FindTask<>(this, helper, spliterator).invoke();
        }
    

    But things have change in 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();
        }
    

    So running the same code under java-9 multiple times will produce a different result.

    There are operations that are already unordered like Stream#generate and Stream#forEach.

    0 讨论(0)
  • 2020-12-06 23:11

    the documentation of Stream#forEach is already said as below:

    The behavior of this operation is explicitly nondeterministic. For parallel stream pipelines, this operation does not guarantee to respect the encounter order of the stream, as doing so would sacrifice the benefit of parallelism.

    so the following test should be pass:

    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)));
    

    and the operation Stream#findAny also is nondeterministic.

    0 讨论(0)
提交回复
热议问题