Java – stream and parallelstream
I have a test code like this:
List<Integer> list = new ArrayList<>(1000000); for(int i=0;i<1000000;i++){ list.add(i); } List<String> values = new ArrayList<>(1000000); list.stream().forEach( i->values.add(new Date().toString()) ); System.out.println(values.size());
Running this, I got a correct output: 1000000
However, if I change stream () to parallelstream (), it is as follows:
list.parallelStream().forEach( i->values.add(new Date().toString()) );
I have a random output, for example: 920821
What's up?
Solution
ArrayList is not synchronized An attempt to add an element to it at the same time is not defined From foreach:
In the second example, you will eventually call add multiple threads on the array list at the same time, and the ArrayList document says:
Wrong solution
If you change the use of ArrayList to vector, you will get the correct results because the list implementation is synchronized Its Javadoc says:
But do not use it! In addition, it may eventually slow down due to explicit synchronization
Correct method
Obviously, this is to avoid the situation that the stream API uses the collect method to provide mutable reduction examples following
List<String> values = list.stream().map(i -> "foo").collect(Collectors.toList());
The correct results will always be provided whether running in parallel or not The stream pipeline handles concurrency and guarantees that it is safe to use a non concurrent collector in a collect operation of a parallel stream Collectors. Tolist () is a built - in collector that accumulates stream elements into a list