给出代码
List<Integer> numbers = Arrays.asList(2, 4, 3);
int sumTotal = numbers.stream().reduce(-3, (x, y) -> x + y + 3);
int multiplyTotal = numbers.stream().reduce(1, (x, y) -> x * y);
是否可以在仅迭代流一次时执行两个操作?
另外,请注意每个reduce都有不同的标识:-3和1。
答案 0 :(得分:4)
您可以使用我在this answer中编写的配对收集器:
int[] result = numbers.stream().collect(
pairing(
Collectors.reducing(0, (x, y) -> x + y + 3),
Collectors.reducing(1, (x, y) -> x * y),
(sum, prod) -> new int[] { sum, prod }));
当然,您可以以任何其他方式组合结果。把它们放到数组只是一个例子。
此收藏夹随时可在我的StreamEx库(MoreCollectors.pairing)中找到。或者你可以使用jOOL库:它有Tuple.collectors方法,它的工作方式类似。
答案 1 :(得分:3)
您可以创建自定义类,并使用可变缩减:
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(2, 4, 3);
Result result = numbers.stream().collect(Result::new, Result::consume, Result::combine);
System.out.println("result = " + result);
}
private static class Result {
private int sum = 0;
private int product = 1;
public void consume(int i) {
sum += i + 3;
product *= i;
}
public void combine(Result r) {
// READ note below
sum += r.sum + 3;
product *= r.product;
}
@Override
public String toString() {
return "Result{" +
"sum=" + sum +
", product=" + product +
'}';
}
}
但是我怀疑你做这件事会因为你正在进行两次迭代而获得更多。
编辑:
请注意,上面的combine()方法在使用并行流时调用,将产生与顺序流不一致的结果。正如Holger在评论中提到的那样,问题是由于操作不遵守减少的身份前提条件这一事实:应用减少任何值V的身份应该产生V,但它产生V + 3以0为身份。
确保不使用并行流来计算结果。
答案 2 :(得分:1)
在JS中,一种解决方案是迭代对象而不是数字。例如:
x
请注意,在您的示例中,y
是“备忘录”(或累加器),Fragment
是当前值。
同样的想法也应该适用于Java。