文章目录
- 297. Java Stream API - Java Stream API 中的 `reduce()` 方法详解
- 🎯 第一种:`reduce(identity, accumulator)`
- ✅ 特点:
- 📌 示例讲解:
- ⚠️ 注意:你提供的 identity 必须真的是该操作的单位元!
- 错误示例:
- 正确示例:
- 🧩 第二种:`reduce(accumulator)` → 返回 `Optional<T>`
- ✅ 特点:
- 📌 示例:取最大值
- 🚨 如果流为空怎么办?
- ✅ 推荐用法:
- 🔁 第三种:`reduce(identity, accumulator, combiner)` → 并行流专用
- ✅ 特点:
- 🧠 背景理解:
- 📌 示例:统计字符串长度总和
- 💡 提取 mapper 表达更清晰:
- 🧠 三种 reduce() 方法对比表:
- 📚 结语:什么时候用哪种?
297. Java Stream API - Java Stream API 中的reduce()方法详解
在 Java Stream 中,reduce()是一个非常核心的终端操作,它可以将流中的所有元素通过一个二元操作折叠成一个最终结果。Stream API 提供了三个重载版本,今天我们将一一解析:
🎯 第一种:reduce(identity, accumulator)
这是最常用也最安全的一种形式,它接受两个参数:
Treduce(Tidentity,BinaryOperator<T>accumulator)✅ 特点:
- 提供了单位元(identity element),即当流为空时返回的默认值。
- 不会返回 Optional,因为总能返回 identity。
- 可用于并行流,并行友好。
📌 示例讲解:
List<Integer>ints=List.of(3,6,2,1);intsum=ints.stream().reduce(0,Integer::sum);System.out.println("sum = "+sum);// 输出:12这个过程等价于:
intresult=0;for(inti:ints){result=result+i;}即使ints是个空集合,reduce()也会返回 0,不会抛异常!
⚠️ 注意:你提供的 identity 必须真的是该操作的单位元!
如果你写错了,Stream API 不会提示你错误,但结果会悄悄错掉!
错误示例:
Stream<Integer>ints=Stream.of(0,0,0,0);intsum=ints.reduce(10,Integer::sum);// ❌ 错误的 identitySystem.out.println("sum = "+sum);// 输出 10,不是 0!正确示例:
Stream<Integer>ints=Stream.of(0,0,0,0);intsum=ints.reduce(0,Integer::sum);System.out.println("sum = "+sum);// ✅ 输出:0✅ 提醒学员:identity 是你负责提供的,必须和操作一致!
🧩 第二种:reduce(accumulator)→ 返回Optional<T>
Optional<T>reduce(BinaryOperator<T>accumulator)✅ 特点:
- 没有 identity,所以返回结果可能为空(比如遇到空流)。
- 使用
Optional包装结果。
📌 示例:取最大值
Stream<Integer>ints=Stream.of(2,8,1,5,3);Optional<Integer>optionalMax=ints.reduce((i1,i2)->i1>i2?i1:i2);System.out.println("result = "+optionalMax.orElseThrow());🟢 输出:
result=8🚨 如果流为空怎么办?
Stream<Integer>empty=Stream.empty();Optional<Integer>optional=empty.reduce(Integer::min);System.out.println(optional.orElse(-1));// 安全返回默认值 -1✅ 推荐用法:
从 Java 10 起,推荐使用orElseThrow()替代get():
optional.orElseThrow();// 安全,可读性好不推荐:
optional.get();// 会抛出 NoSuchElementException🔁 第三种:reduce(identity, accumulator, combiner)→ 并行流专用
<U>Ureduce(Uidentity,BiFunction<U,?superT,U>accumulator,BinaryOperator<U>combiner);✅ 特点:
- 支持映射 + 累加一步完成。
identity是 combiner 的单位元。- 可以把元素转换为另一种类型(泛型 U)。
🧠 背景理解:
适合并行流时,流被切分成多个片段,每个片段部分归约后,需要用combiner合并成总结果。
📌 示例:统计字符串长度总和
Stream<String>strings=Stream.of("one","two","three","four");intresult=strings.reduce(0,// identity 是 0(partialSum,str)->partialSum+str.length(),// accumulatorInteger::sum// combiner);System.out.println("sum = "+result);// 输出:15💡 提取 mapper 表达更清晰:
Function<String,Integer>mapper=String::length;BiFunction<Integer,String,Integer>accumulator=(partialSum,str)->partialSum+mapper.apply(str);这样表达更清楚:映射 + 累加分别负责什么角色。
🧠 三种 reduce() 方法对比表:
| 方法签名 | 返回类型 | 是否要求 identity | 是否返回 Optional | 空流行为 | 并行友好性 |
|---|---|---|---|---|---|
reduce(identity, accumulator) | T | ✅ 是 | ❌ 否 | 返回 identity | ✅ |
reduce(accumulator) | Optional<T> | ❌ 否 | ✅ 是 | 返回 Optional.empty() | ❌ 不推荐 |
reduce(identity, accumulator, combiner) | U | ✅ 是 | ❌ 否 | 返回 identity | ✅ 强推荐并行用 |
📚 结语:什么时候用哪种?
| 需求 | 使用方法 |
|---|---|
| 你知道 identity,且只处理本类型 | reduce(identity, accumulator) |
没有 identity,比如min()、max() | reduce(accumulator),处理 Optional |
| 需要先映射再 reduce,或并行流合并 | reduce(identity, accumulator, combiner) |