java stream自定义收集器是围绕归约本质设计的轻量协作机制,通过collector.of()分离准备容器、添加元素、合并结果、产出终值四步,支持高效并行与组合嵌套。

Java Stream API 的自定义收集器(Custom Collector)不是“写个类凑数”,而是围绕归约本质设计的轻量协作机制。它不依赖对象封装,重在清晰分离“准备容器”“添加元素”“合并中间结果”“产出终值”四个动作,让复杂聚合既可控又可并行。
用 Collector.of() 快速组装逻辑
绝大多数自定义场景无需实现 Collector 接口,直接调用 Collector.of() 即可。它接收四个函数式参数:
-
supplier:提供初始累加器,比如
ArrayList::new、() -> new int[1]或AtomicInteger::new -
accumulator:定义如何把单个元素加入累加器,如
(list, e) -> list.add(e)或(count, e) -> count.incrementAndGet() -
combiner:用于并行流中合并两个累加器,例如
(a1, a2) -> { a1.addAll(a2); return a1; } -
finisher:将累加器转为最终结果,如
list -> list.stream().sorted().limit(10).toList()
若 finisher 是恒等操作(比如返回原 list),可传入 Characteristics.IDENTITY_FINISH 提升性能。
选对累加器类型,省去额外包装
累加器(A 类型)不必是专门类,越贴近业务状态越简洁:
- 统计计数:用
int[1]或AtomicInteger,避免 Integer 对象创建开销 - 分组+汇总混合:用
Map<k double></k>,其中数组存 sum/count/min/max 等多个指标 - TopN 场景:直接用
PriorityQueue<t></t>作为累加器,插入时自动维护堆结构 - 字符串拼接:用
StringBuilder,比反复创建 String 高效得多
声明特性,让并行更安全高效
第 5 个参数 characteristics 是提示,不是强制约束,但影响运行时行为:
- CONCURRENT:表示累加器本身线程安全(如 ConcurrentHashMap),此时 combiner 可能被跳过
- UNORDERED:说明结果不依赖输入顺序,允许 Stream 在并行时自由调度,提升吞吐
- IDENTITY_FINISH:finisher 不做转换,直接返回累加器,避免一次无谓的函数调用
错误声明(如给 ArrayList 声明 CONCURRENT)会导致数据竞争;不声明而实际支持,可能错过优化机会。
嵌套下游收集器处理层级聚合
复杂归约常需“先分组,再各自统计”。这时不用手写两层循环,而是组合已有收集器:
- 按部门分组后求平均薪资:
groupingBy(Dish::getType, averagingInt(Dish::getCalories)) - 先分区(是否素食),再每区取价格最高菜品:
partitioningBy(Dish::isVegetarian, collectingAndThen(maxBy(comparingInt(Dish::getPrice)), Optional::get)) - 多级分组(部门→职位→平均工资):嵌套使用
groupingBy,下游仍可接averagingDouble或自定义收集器
这种组合方式复用成熟逻辑,避免重复实现,也利于单元测试拆分。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











