What do the Stream reduce() requirements exactly entail?

前端 未结 3 1056
无人及你
无人及你 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 12:02

    Let me give two examples. First where the identity is broken:

    int result = Stream.of(1, 2, 3, 4, 5, 6)
            .parallel()
            .reduce(10, (a, b) -> a + b);
    
    System.out.println(result); // 81 on my run
    

    Basically you have broken this rule: The identity value must be an identity for the accumulator function.  This means that for all u, accumulator(identity, u) is equal to u.

    Or to make is simpler, let's see if that rule holds for some random data from our Stream:

     Integer identity = 10;
     BinaryOperator combiner = (x, y) -> x + y;
     boolean identityRespected = combiner.apply(identity, 1) == 1;
     System.out.println(identityRespected); // prints false
    

    And a second example:

    /**
     * count letters, adding a bit more all the time
     */
    private static int howMany(List tokens) {
        return tokens.stream()
                .parallel()
                .reduce(0, // identity
                        (i, s) -> { // accumulator
                            return s.length() + i;
                        }, (left, right) -> { // combiner
                            return left + right + left; // notice the extra left here
                        });
    }
    

    And you invoke this with:

    List left = Arrays.asList("aa", "bbb", "cccc", "ffffffffd", "eeeeee");
    List right = Arrays.asList("aa", "bbb", "cccc", "ffffffffd", "eeeeee", "");
    
    System.out.println(howMany(left));  // 38 on my run
    System.out.println(howMany(right)); // 50 on my run
    

    Basically you have broken this rule: Additionally, the combiner function must be compatible with the accumulator function or in code :

    // this must hold!
    // combiner.apply(u, accumulator.apply(identity, t)) == accumulator.apply(u, t)
    
    Integer identity = 0;
    String t = "aa";
    Integer u = 3; // "bbb"
    BiFunction accumulator = (Integer i, String s) -> i + s.length();
    BinaryOperator combiner = (left, right) -> left + right + left;
    
    int first = accumulator.apply(identity, t); // 2
    int second = combiner.apply(u, first); // 3 + 2 + 3 = 8
    
    Integer shouldBe8 = accumulator.apply(u, t);
    
    System.out.println(shouldBe8 == second); // false
    

提交回复
热议问题