使用标识组合器并行流减少

时间:2017-09-24 01:48:33

标签: java-8 java-stream reduce

final Stream<Integer> numbers = Stream.of(5, 3, 2, 7, 3, 13, 7).parallel();

为什么以下行的输出是7?

 numbers.reduce(1, (a, b) -> a + b, (x, y) -> x - y)); 

1 个答案:

答案 0 :(得分:4)

我没有从评论中查看该链接,但文档非常清楚identity,它甚至提供了一种简单的测试方法:

  

标识值必须是组合器函数的标识。这意味着对于所有u,组合器(identity,u)等于u

所以让我们简化一下你的例子:

Stream<Integer> numbers = Stream.of(3, 1).parallel();
BiFunction<Integer, Integer, Integer> accumulator = (a, b) -> a + b;

BiFunction<Integer, Integer, Integer> combiner = (x, y) -> x - y; 

    int result = numbers.reduce(
            1,
            accumulator,
            combiner);

    System.out.println(result);

让我们说u = 3(只是Stream中的一个随机元素),因此:

    int identity = 1;
    int u = 3;

    int toTest = combiner.apply(identity, u);
    System.out.println(toTest == identity); // must be true, but is false

即使你认为你会用zero取代身份,那也行不通;文档提出了另一个论点:

  

此外,组合器功能必须与累加器功能兼容;对于所有你和你,必须具备以下条件:

 combiner.apply(u, accumulator.apply(identity, t)) == accumulator.apply(u, t)

您可以进行相同的测试:

int identity = 0;
int u = 3;
int t = 1;

boolean associativityRespected = 
     combiner.apply(u, accumulator.apply(identity, t)) == accumulator.apply(u, t);
System.out.println(associativityRespected); // prints false