Java Stream的reduce方法用于函数式归约,支持并行、无状态、不可变操作;常用三参数形式求和,双参数返回Optional,对象字段求和需先map或用mapToInt,注意accumulator无状态及combiner结合律要求。

Java Stream 的 reduce 方法用于将流中所有元素按指定规则合并成一个结果,求和是最常见的使用场景之一。 它不是简单循环累加,而是支持并行、无状态、不可变的函数式归约操作。
基础用法:单参数 reduce(需提供初始值)
最常用的是带初始值的三参数 reduce(identity, accumulator, combiner),适合求和:
- identity:初始值(如 0),也是空流时的返回值
-
accumulator:二元操作,接收“当前结果”和“下一个元素”,返回新结果(如
(sum, x) -> sum + x) -
combiner:仅在并行流中使用,合并两个部分结果(如
(sum1, sum2) -> sum1 + sum2)
示例:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4);int sum = numbers.stream()
.reduce(0, (a, b) -> a + b, Integer::sum); // 结果:10
简化写法:双参数 reduce(返回 Optional)
不提供初始值时,用 reduce(BinaryOperator),返回 Optional<T>,避免空流异常:
立即学习“Java免费学习笔记(深入)”;
- 流为空时返回
Optional.empty(),需显式处理 - 适用于不确定流是否非空的场景
示例:
Optional<Integer> sumOpt = numbers.stream().reduce(Integer::sum);int sum = sumOpt.orElse(0); // 安全获取,默认为 0
对对象字段求和:先 map 再 reduce
若要对对象的某个数值字段求和(如商品价格),先用 map 提取字段,再归约:
- 确保 map 后得到的是数值类型(如
Integer、Double) - 推荐使用
mapToInt等原始类型特化流,避免装箱开销
示例:
List<Product> products = ...;int total = products.stream()
.mapToInt(Product::getPrice)
.reduce(0, Integer::sum);
注意点与常见误区
- accumulator 必须是无状态、不可变、引用透明的:不能修改外部变量或依赖可变状态
- combiner 在串行流中不会被调用,但必须提供且满足结合律(如
+满足,-不满足) - 对于基本类型求和,优先用
mapToInt().sum()这类终端操作,更简洁高效 - 不要用
reduce做复杂逻辑聚合(如分组统计),应考虑collect配合Collectors


















