在Stream reduce方法中,求和必须始终为0,乘法必须始终为1吗?

In Stream reduce method, must the identity always be 0 for sum and 1 for multiplication?(在Stream reduce方法中,求和必须始终为0,乘法必须始终为1吗?)

本文介绍了在Stream reduce方法中,求和必须始终为0,乘法必须始终为1吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我继续学习 java 8.

I proceed with java 8 learning.

我发现了一个有趣的行为:

I have found an interesting behavior:

让我们看看代码示例:

// identity value and accumulator and combiner
Integer summaryAge = Person.getPersons().stream()
        //.parallel()  //will return surprising result
        .reduce(1,
                (intermediateResult, p) -> intermediateResult + p.age,
                (ir1, ir2) -> ir1 + ir2);
System.out.println(summaryAge);

和模型类:

public class Person {

    String name;

    Integer age;
    ///...

    public static Collection<Person> getPersons() {
        List<Person> persons = new ArrayList<>();
        persons.add(new Person("Vasya", 12));
        persons.add(new Person("Petya", 32));
        persons.add(new Person("Serj", 10));
        persons.add(new Person("Onotole", 18));
        return persons;
   }
}

12+32+10+18 = 72.对于顺序流,此代码始终返回 73,即 72 + 1,但对于并行,它始终返回 76,即 72 +4*1(4 等于流元素数).

12+32+10+18 = 72. For sequential stream, this code always returns 73 which is 72 + 1 but for parallel, it always returns 76 which is 72 + 4*1 (4 is equal to stream elements count).

当我看到这个结果时,我认为并行流和顺序流返回不同的结果很奇怪.

When I saw this result I thought that it is strange that parallel stream and sequential streams return different results.

我是不是在什么地方违约了?

Am I broke contract somewhere?

对我来说,73 是预期结果,但 76 不是.

for me, 73 is expected result but 76 is not.

推荐答案

identity值是一个值,使得x op identity = x.这不是 Java Stream 所独有的概念,例如参见 on Wikipedia.

The identity value is a value, such that x op identity = x. This is a concept which is not unique to Java Streams, see for example on Wikipedia.

它列出了一些标识元素的例子,其中一些可以直接用Java代码表示,例如

It lists some examples of identity elements, some of them can be directly expressed in Java code, e.g.

  • reduce("", String::concat)
  • reduce(true, (a,b) -> a&&b)
  • reduce(false, (a,b) -> a||b)
  • reduce(Collections.emptySet(),(a,b)->{设置<X>s=新哈希集<>(a);s.addAll(b);返回 s;})
  • reduce(Double.POSITIVE_INFINITY, Math::min)
  • reduce(Double.NEGATIVE_INFINITY, Math::max)

应该清楚的是,任意x的表达式x + y == x只能在y==0时满足,因此 0 是加法的标识元素.同样,1 是乘法的标识元素.

It should be clear that the expression x + y == x for arbitrary x can only be fulfilled when y==0, thus 0 is the identity element for the addition. Similarly, 1 is the identity element for the multiplication.

更复杂的例子是

  • 减少谓词流

  • Reducing a stream of predicates

reduce(x->true, Predicate::and)
reduce(x->false, Predicate::or)

  • 减少函数流

  • Reducing a stream of functions

    reduce(Function.identity(), Function::andThen)
    

  • 这篇关于在Stream reduce方法中,求和必须始终为0,乘法必须始终为1吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

    本文标题为:在Stream reduce方法中,求和必须始终为0,乘法必须始终为1吗?

    基础教程推荐