我着手进行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
。对于顺序流,此代码始终返回73
的72 + 1
,但对于并行流,则始终返回76
的72 + 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/