What do the Stream reduce() requirements exactly entail?

前端 未结 3 1054
无人及你
无人及你 2020-12-06 11:41

When using the reduce() operation on a parallel stream, the OCP exam book states that there are certain principles the reduce() arguments must adhe

3条回答
  •  陌清茗
    陌清茗 (楼主)
    2020-12-06 11:43

    why isn't the accumulator associative?

    It's not associative since the order of subtraction operations determines the final result.

    If you run a serial Stream, you'll get the expected result of:

    0 - 1 - 2 - 3 - 4 - 5 - 6 = -21
    

    On the other hand, for parallel Streams, the work is split to multiple threads. For example, if reduce is executed in parallel on 6 threads, and then the intermediate results are combined, you can get a different result:

    0 - 1   0 - 2   0 - 3      0 - 4     0 - 5    0 - 6
      -1     -2      -3         -4        -5        -6
    
      -1 - (-2)         -3 - (-4)          -5 - (-6)
          1                 1                  1
               1   -   1
                   0            -     1
    
                            -1
    

    Or, to make a long example short:

    (1 - 2) - 3 = -4
    1 - (2 - 3) =  2
    

    Therefore subtraction is not associative.

    On the other hand, a+b doesn't cause the same problem, since addition is an associative operator (i.e. (a+b)+c == a+(b+c)).

    The problem with the identity example is that when reduce is executed in parallel on multiple threads, "X" is appended to the starts of each intermediate result.

    What exactly would be a proper identity to use then?

    If you change the identity value to "" :

    System.out.println(Arrays.asList("w","o","l","f"))
    .parallelStream()
    .reduce("", String::concat));
    

    you'll get "wolf" instead of "XwXoXlXf".

提交回复
热议问题