The following code prints true for 100 times:
for(int i=0; i<100; i++) {
String s2 = Arrays.asList("A", "E", "I", "O", "U").parallelStream().reduce("x", String::concat, String::concat);
System.out.println("xAxExIxOxU".equals(s2));
}
Granted, 100 times is not a guarantee. But doesn't it seem though that even if the identity used here does not meet the requirement "...for all u, combiner.apply(identity, u) is equal to u" per the doc, we can still say that a parallel stream derived from a list or any other inherently ordered structure will behave just like a sequential stream in reduce() returning the same output?
Parallel streams enable us to execute code in parallel on separate cores. The final result is the combination of each individual outcome.
Similarly, don't use parallel if the stream is ordered and has much more elements than you want to process, e.g. This may run much longer because the parallel threads may work on plenty of number ranges instead of the crucial one 0-100, causing this to take very long time.
It is important to ensure that the result of the parallel stream is the same as is obtained through the sequential stream, so the parallel streams must be stateless, non-interfering, and associative.
In the case of a sequential stream, the content of the list is printed in an ordered sequence. The output of the parallel stream, on the other hand, is unordered and the sequence changes every time the program is run. This signifies at least one thing: that invocation of the list.
The Javadoc for the Stream.reduce
function with an identity argument says:
The identity value must be an identity for the accumulator function. This means that for all t, accumulator.apply(identity, t) is equal to t.
Which is clearly not the case here - "x".concat(anything)
doesn't equal anything
. The only valid identity value here is ""
.
If you had tested the premise of the title of your question - by seeing what a non-parallel operation returns - you'd see that the answer to your title is "no" - because a non-parallel stream returns "xAEIOU"
for your reduce operation.
If you change the identity value from "x"
to ""
, then the answer would be "yes, there is such a guarantee, as your reduce function is associative and the constraints on the identity value are also satisfied."
Even with your modified title, the answer is clear:
You are breaking the contract of the reduce
function by providing, as the identity value, a value that is not an identity value for your reduce function. As such, since you are breaking the contract of the reduce
methods, all guarantees are off.
It's easy to create a case where it doesn't hold; just make your list larger like Holger already pointed out:
List<String> list = new ArrayList<>();
for (int i = 0; i < 500; i++) {
list.add("A");
}
String s2 = list.parallelStream().reduce("x", String::concat, String::concat);
System.out.println(s2);
if (s2.length() != list.size() * 2) {
System.out.println("Bad s2 size");
}
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