文章目录
- [325. Java Stream API - 理解 Collector 的三大特性:助力流处理优化](#325. Java Stream API - 理解 Collector 的三大特性:助力流处理优化)
-
- [✨ 什么是 Collector 的特性?](#✨ 什么是 Collector 的特性?)
- [🔍 三种核心特性详解](#🔍 三种核心特性详解)
- [🧪 示例讲解每个特性](#🧪 示例讲解每个特性)
-
- [✅ `IDENTITY_FINISH`:无需转换,直接返回中间结果](#✅
IDENTITY_FINISH:无需转换,直接返回中间结果) - [🔁 `UNORDERED`:顺序无关,性能优先](#🔁
UNORDERED:顺序无关,性能优先) - [⚙️ `CONCURRENT`:支持并发累积,适合并行流](#⚙️
CONCURRENT:支持并发累积,适合并行流)
- [✅ `IDENTITY_FINISH`:无需转换,直接返回中间结果](#✅
- [🚦 特性组合示意](#🚦 特性组合示意)
- [🎯 特性总结对照表](#🎯 特性总结对照表)
- [📌 小贴士](#📌 小贴士)
325. Java Stream API - 理解 Collector 的三大特性:助力流处理优化
在 Java Stream API 中,自定义或使用收集器(Collector)时,我们可以通过定义 特性(Characteristics) 来告诉流引擎如何优化执行过程。理解这些特性,不仅有助于你写出更高效的 Collector,也能帮助你掌握流在并行或顺序执行中的行为。
✨ 什么是 Collector 的特性?
每个 Collector 都可以声明一些内部特性(characteristics) ,它们由 Collector.Characteristics 枚举类型定义。
这些特性由 Collector 接口中的 characteristics() 方法返回,返回类型为 Set<Collector.Characteristics>,用于指示该收集器的行为约定,进而帮助 Stream 更好地优化执行。
🔍 三种核心特性详解
| 特性名 | 描述 | 适用场景 |
|---|---|---|
IDENTITY_FINISH |
表示中间容器本身就是最终结果,因此不需要调用 finisher() 方法。 |
如:toList() 内部用的是 ArrayList,返回的就是它本身 |
UNORDERED |
表示不保证元素处理顺序 | 如:toSet() 不保证顺序 |
CONCURRENT |
表示支持并发累加器,可在并行流中安全使用 | 如:使用线程安全结构如 ConcurrentHashMap |
🧪 示例讲解每个特性
✅ IDENTITY_FINISH:无需转换,直接返回中间结果
java
Collector<String, List<String>, List<String>> toListCollector = new Collector<>() {
public Supplier<List<String>> supplier() {
return ArrayList::new;
}
public BiConsumer<List<String>, String> accumulator() {
return List::add;
}
public BinaryOperator<List<String>> combiner() {
return (list1, list2) -> {
list1.addAll(list2);
return list1;
};
}
public Function<List<String>, List<String>> finisher() {
return Function.identity(); // 不做任何转换
}
public Set<Characteristics> characteristics() {
return Set.of(Characteristics.IDENTITY_FINISH);
}
};
🧠 说明 :
因为 A(中间容器)和 R(最终结果)类型一致,finisher() 只是返回自己,因此可以声明 IDENTITY_FINISH,流引擎将跳过调用 finisher() 提升性能。
🔁 UNORDERED:顺序无关,性能优先
java
Set<String> result = Stream.of("A", "B", "C", "A", "B")
.collect(Collectors.toSet()); // Set 无序
🧠 说明 :
Collectors.toSet() 返回的收集器声明了 UNORDERED,意味着它不关心流中元素的顺序,甚至在并行时可能顺序完全打乱。这样可以减少排序或同步开销。
⚙️ CONCURRENT:支持并发累积,适合并行流
java
Collector<String, ?, ConcurrentMap<Integer, List<String>>> concurrentCollector =
Collectors.groupingByConcurrent(String::length);
ConcurrentMap<Integer, List<String>> map = List.of("one", "three", "four", "five", "six", "seven")
.parallelStream() // 并行流
.collect(concurrentCollector);
🧠 说明 :
该收集器声明了 CONCURRENT,表示其使用了线程安全的数据结构(如 ConcurrentMap),可以在并行流中安全使用,无需锁。
🚦 特性组合示意
java
@Override
public Set<Characteristics> characteristics() {
return Set.of(
Characteristics.CONCURRENT,
Characteristics.UNORDERED,
Characteristics.IDENTITY_FINISH
);
}
🧠 提示 :组合多个特性时,Stream API 会据此自动选择并行策略、是否执行 finisher、是否保证顺序等优化策略。
🎯 特性总结对照表
| 特性名 | 是否可省略 finisher | 是否保证顺序 | 是否线程安全 |
|---|---|---|---|
IDENTITY_FINISH |
✅ 是 | 🔶 不保证(视其他特性) | 🔶 不保证 |
UNORDERED |
❌ 否 | ❌ 否 | 🔶 可能是 |
CONCURRENT |
❌ 否 | ❌ 否 | ✅ 是 |
📌 小贴士
- 如果你写的收集器返回的就是累加容器本身,记得加上
IDENTITY_FINISH! - 想要并行处理但又安全?使用
CONCURRENT并搭配线程安全结构。 - 如果你对元素顺序无所谓,那就大胆用
UNORDERED获取更多优化空间!