Is it possible that a parallel stream could give a different result than a serial stream in Java 8? According to my information, a parallel stream is the same as a serial stream except divided into multiple substreams. It is a question of speed. All operations over the elements are done and the results of the substreams are combined at the end. In the end, the result of the operations should be the same for parallel and serial streams in my opinion. So my question is, is it possible that this code could give me a different result? And if it is possible, why does it happen?
int[] i = {1, 2, 5, 10, 9, 7, 25, 24, 26, 34, 21, 23, 23, 25, 27, 852, 654, 25, 58};
Double serial = Arrays.stream(i).filter(si -> {
return si > 5;
}).mapToDouble(Double::new).map(NewClass::add).reduce(Math::atan2).getAsDouble();
Double parallel = Arrays.stream(i).filter(si -> {
return si > 5;
}).parallel().mapToDouble(Double::new).map(NewClass::add).reduce(Math::atan2).getAsDouble();
System.out.println("serial: " + serial);
System.out.println("parallel: " + parallel);
public static double add(double i) {
return i + 0.005;
}
and results are:
serial: 3.6971567726175894E-23
parallel: 0.779264049587662
atan2makes no sense at all. It is not associative for example.si -> { return si > 5; }should be justsi -> si > 5, and you'd want to do the filter after theparallel()..parallel()anywhere between stream start and terminal operation, the result will be the same..mapToDouble(Double::new)is widening eachinttodouble, boxing them intoDoubleobjects, just to unbox them afterwards todoublevalue. If you want to convertinttodouble, a.mapToDouble(i->i)would be much more straightforward, skipping the object creation. But even simpler is.asDoubleStream()… And, if you really need boxed values, useDouble::valueOfinstead ofDouble::new.