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.
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
.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With