Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

search for example of inconsistent behavior java-8 stream?

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

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

my question is quite simple : is there an easy way to illustrate this fact in a little unit test (maybe with an HashMap or some thing like this) ?

[Edit] the whole quote is here :

For sequential streams, the presence or absence of an encounter order does not affect performance, only determinism. If a stream is ordered, repeated execution of identical stream pipelines on an identical source will produce an identical result; if it is not ordered, repeated execution might produce different results.

Thus, my question is about a strictly sequential not parallele execution. It is this case that I'm questioning about.

like image 547
Lyxthe Lyxos Avatar asked Sep 05 '25 17:09

Lyxthe Lyxos


2 Answers

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.

like image 69
Eugene Avatar answered Sep 08 '25 23:09

Eugene


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.

like image 36
holi-java Avatar answered Sep 08 '25 21:09

holi-java