Java自定义Collector需实现supplier、accumulator、combiner、finisher和characteristics五个方法:supplier提供新容器,accumulator定义单元素累积逻辑,combiner支持并行归并,finisher转换最终结果,characteristics告知流框架行为特征以优化性能。

Java 中自定义 Collector 的核心是实现 Collector 接口的五个方法:supplier、accumulator、combiner、finisher 和 characteristics。关键在于理解每个方法的职责,以及如何配合完成并行流下的安全聚合。
明确收集目标和中间容器
先想清楚你要收集成什么结果(比如统计字符串长度分布、构建不可变列表、计算加权平均),再决定用什么类型作为“中间累积容器”。这个容器不一定是最终返回类型——finisher 负责最后转换。
- 如果最终要返回
Map<String, Long>(词频统计),中间容器可以是HashMap<String, Long> - 如果要返回不可变集合,中间容器可用
ArrayList,finisher再转成ImmutableList或List.copyOf - 避免在
accumulator中直接修改最终结果对象(如final List),否则会线程不安全
正确实现 supplier、accumulator 和 combiner
supplier 返回新的空容器;accumulator 定义“把一个元素加进去”的逻辑;combiner 定义“把两个容器合并”的逻辑——三者必须行为一致,且 combiner 必须支持并行流分段归并。
-
supplier:返回新实例,例如() -> new HashMap<>() -
accumulator:例如(map, str) -> map.merge(str, 1L, Long::sum) -
combiner:例如(map1, map2) -> { map2.forEach((k, v) -> map1.merge(k, v, Long::sum)); return map1; } - 注意:
combiner必须能处理任意两个中间容器的合并,不能假定顺序或结构
finisher 决定最终输出形式
finisher 是可选但常用的一环,用于将中间容器转为业务需要的不可变/规范形态。如果不需转换,可返回 Function.identity()。
立即学习“Java免费学习笔记(深入)”;
- 返回不可变 Map:
map -> Collections.unmodifiableMap(map) - 返回排序后的键值对列表:
map -> map.entrySet().stream().sorted(Map.Entry.comparingByKey()).toList() - 若中间容器已是最终类型(如用
TreeSet收集去重字符串),finisher可直接返回Function.identity()
合理设置 characteristics 提升性能
characteristics 是一组枚举标志,告知流框架该收集器的行为特征,影响是否启用并行优化或跳过某些检查。
-
CONCURRENT:表示中间容器本身线程安全(如ConcurrentHashMap),此时combiner可能不会被调用(并行时各线程直接往同一容器塞) -
UNORDERED:表示收集结果不依赖输入顺序(如求和、计数),允许流引擎重排元素提升效率 -
IDENTITY_FINISH:表示finisher是恒等函数,可省略转换步骤 - 不要随意加
CONCURRENT—— 必须确保supplier返回的容器真能安全并发更新,且accumulator使用的是线程安全操作


















