Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Stream stateful behavior example

The package summary of java.util.stream states the following:

An example of a stateful lambda is the parameter to map() in:

Set<Integer> seen = Collections.synchronizedSet(new HashSet<>());
stream.parallel().map(e -> { if (seen.add(e)) return 0; else return e; })...

Here, if the mapping operation is performed in parallel, the results for the same input could vary from run to run, due to thread scheduling differences, whereas, with a stateless lambda expression the results would always be the same.

I don't understand why this wouldn't produce consistent results, given that the set is synchronized and can only process one element at a time. Can you complete the above example in a way that demonstrates how the result could vary due to parallelization?

like image 730
shmosel Avatar asked May 25 '17 03:05

shmosel


2 Answers

List<Integer> numbers = // fill it in with [1, 3, 3, 5]
List<Integer> collected = numbers.stream().parallel().map(...).collect(Collectors.toList());

collected could contain either [0, 0, 3, 0] or [0, 3, 0, 0], depending on which of the middle two elements was processed first.

like image 76
Douglas Avatar answered Oct 25 '22 02:10

Douglas


I'm not sure if this counts as a stateful per-se (if it does not I'll just delete this), but relying on anything that has state inside map and the like is bad.

int[] arr = new int[3];
    Stream.of(1, 2, 3)
            .map(i -> {
                arr[i] = i + 5;
                return i * 2;
            })
            .count();

    System.out.println(Arrays.toString(arr));

In jdk-9 this will produce an array with zeroes only, since there are no operations that change the Stream size (flatmap or filter), thus map is never executed.

like image 28
Eugene Avatar answered Oct 25 '22 03:10

Eugene