Combiner 永远不会在缩减操作中被调用(但是是强制性的)
Combiner never gets called in reduction operation (but is mandatory)
我想弄清楚累加器和组合器在 reduce
流操作中的作用。
List<User> users = Arrays.asList(new User("John", 30), new User("Julie", 35));
int result = users.stream()
.reduce(0,
(partialAgeResult, user) -> {
// accumulator is called twice
System.out.println(MessageFormat.format("partialAgeResult {0}, user {1}", partialAgeResult, user));
return partialAgeResult + user.getAge();
},
(integer, integer2) -> {
// combiner is never called
System.out.println(MessageFormat.format("integer {0}, integer2 {1}", integer, integer2));
return integer * integer2;
});
System.out.println(MessageFormat.format("Result is {0}", result));
我注意到组合器从未执行过,结果是 65。
如果我使用 users.parallelStream()
然后组合器执行一次,结果是 1050.
为什么 stream
和 parallelStream
会产生不同的结果?我没有看到并行执行它的任何副作用。
简单流版本中组合器的用途是什么?
问题就在这里。您正在乘法而不是在您的组合器中添加。
(integer, integer2) -> {
// combiner is never called
System.out.println(MessageFormat.format("integer {0}, integer2 {1}", integer, integer2));
return integer * integer2; //<----- Should be addition
});
组合器用于适当组合并行操作的各个部分,因为这些操作可以独立地对原始流的各个“部分”执行。
一个简单的例子就是对元素列表求和。并行操作中可能有多种部分和,因此需要在组合器中对部分和进行求和以获得总和(一个很好的练习,你自己试试看)。
对于累加器参数或实现类型之间不匹配的顺序流 ( BiFunction<U,? super T,U>
),您必须提供组合器但从未调用过,因为您不需要组合部分结果并行计算。
因此您可以通过在 reduce 之前转换为部分数据来简化此操作,以避免给出组合器。
users.stream().map(e -> e.getAge()).reduce(0, (a, b) -> a + b);
所以,对于顺序流,使用像 BiFunction<U,? super T,U>
这样的带有累加器的组合器实际上是没有意义的,但是你必须提供,因为没有像
这样的方法
reduce(U identity, BiFunction<U,? super T,U> accumulator)
但是对于并行流合并器调用。
你得到 1050 因为你乘以组合器意味着 (30*35).
我想弄清楚累加器和组合器在 reduce
流操作中的作用。
List<User> users = Arrays.asList(new User("John", 30), new User("Julie", 35));
int result = users.stream()
.reduce(0,
(partialAgeResult, user) -> {
// accumulator is called twice
System.out.println(MessageFormat.format("partialAgeResult {0}, user {1}", partialAgeResult, user));
return partialAgeResult + user.getAge();
},
(integer, integer2) -> {
// combiner is never called
System.out.println(MessageFormat.format("integer {0}, integer2 {1}", integer, integer2));
return integer * integer2;
});
System.out.println(MessageFormat.format("Result is {0}", result));
我注意到组合器从未执行过,结果是 65。
如果我使用 users.parallelStream()
然后组合器执行一次,结果是 1050.
为什么 stream
和 parallelStream
会产生不同的结果?我没有看到并行执行它的任何副作用。
简单流版本中组合器的用途是什么?
问题就在这里。您正在乘法而不是在您的组合器中添加。
(integer, integer2) -> {
// combiner is never called
System.out.println(MessageFormat.format("integer {0}, integer2 {1}", integer, integer2));
return integer * integer2; //<----- Should be addition
});
组合器用于适当组合并行操作的各个部分,因为这些操作可以独立地对原始流的各个“部分”执行。
一个简单的例子就是对元素列表求和。并行操作中可能有多种部分和,因此需要在组合器中对部分和进行求和以获得总和(一个很好的练习,你自己试试看)。
对于累加器参数或实现类型之间不匹配的顺序流 ( BiFunction<U,? super T,U>
),您必须提供组合器但从未调用过,因为您不需要组合部分结果并行计算。
因此您可以通过在 reduce 之前转换为部分数据来简化此操作,以避免给出组合器。
users.stream().map(e -> e.getAge()).reduce(0, (a, b) -> a + b);
所以,对于顺序流,使用像 BiFunction<U,? super T,U>
这样的带有累加器的组合器实际上是没有意义的,但是你必须提供,因为没有像
reduce(U identity, BiFunction<U,? super T,U> accumulator)
但是对于并行流合并器调用。 你得到 1050 因为你乘以组合器意味着 (30*35).