我使用Java Stream Reduce编写了以下代码示例:
Person reducedPerson = Person.getPersons().stream()
.parallel() //will return surprising result
.reduce(new Person(), (intermediateResult, p2) -> {
intermediateResult.setAge(intermediateResult.getAge() + p2.getAge());
return intermediateResult;
},
(ir1, ir2) -> {
ir1.setAge(ir1.getAge() + ir2.getAge());
return ir1;
});
System.out.println(reducedPerson);
模型:
public class Person {
String name;
Integer age;
public Person() {
age = 0;
name = "default";
}
//...
public Person(String name, Integer age) {
this.name = name;
this.age = 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;
}
}
每个代码示例执行的结果都不同:
例如:
Person{name='默认', age=256}
或者
Person{name='default', age=248}
我已经确定问题在combiner
中,因为在顺序流代码中执行正确。
请帮忙纠正组合器。
P.S.
期望的结果是名称为“default”的人和年龄为72岁(列表中所有人的总年龄)。
P.S.
对于整数的相同代码作为缩小结果可以正常工作:
Integer age = Person.getPersons().stream()
.parallel()
.reduce(0, (intermediateResult, p2) -> {
intermediateResult = intermediateResult + p2.getAge();
return intermediateResult;
}, (ir1, ir2) -> {
System.out.println("combiner");
ir1 = ir1 + ir2;
return ir1;
});
System.out.println(age);
reduce
调用违反了合同的所有可能部分。请阅读文档。您不应该在流中改变对象。 - Boris the Spiderreduce
的三个参数版本而不是两个参数版本,因为累加器与输入具有相同的类型。 - Louis WassermanPerson.getPersons().stream().parallel().mapToInt(Person::getAge).sum()
呢?为什么需要生成一个Person
而不是一个求和后的年龄,后者会更合乎逻辑呢? - Louis Wasserman