我着手进行Java 8学习。

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

让我们看一下代码示例:

// 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。对于顺序流,此代码始终返回7372 + 1,但对于并行流,则始终返回7672 + 4*1(4等于流元素计数)。

当我看到此结果时,我以为并行流和顺序流返回不同的结果很奇怪。

我在某处违约了吗?

附言

对我来说,预期结果为73,但并非预期结果。

最佳答案

标识值是一个值,例如x op identity = x。这是Java Stream所独有的概念,例如on Wikipedia

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

  • reduce("", String::concat)
  • reduce(true, (a,b) -> a&&b)
  • reduce(false, (a,b) -> a||b)
  • reduce(Collections.emptySet(), (a,b)->{ Set<X> s=new HashSet<>(a); s.addAll(b); return s; })
  • reduce(Double.POSITIVE_INFINITY, Math::min)
  • reduce(Double.NEGATIVE_INFINITY, Math::max)

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

    更复杂的例子是
  • 减少谓词流
    reduce(x->true, Predicate::and)
    reduce(x->false, Predicate::or)
    
  • 减少功能流
    reduce(Function.identity(), Function::andThen)
    
  • 关于java - 在Stream reduce方法中,对于总和而言,标识必须始终为0,对于乘法而言,标识始终为1?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/32866581/

    10-16 04:54