当前位置: 首页 > news >正文

324. Java Stream API - 实现 Collector 接口:自定义你的流式收集器

文章目录

  • 324. Java Stream API - 实现 `Collector` 接口:自定义你的流式收集器
    • 🔍 为什么要实现 `Collector` 接口?
    • ☕ 自定义 Collector 的三种方式
    • 📐 理解 `Collector<T, A, R>` 的三个类型参数
      • 🚗 举例说明
    • 📋 代码示例:查看 `Collector` 类型参数
    • 🧪 补充示例:自定义 Collector 实现(首字母统计)
    • 🧠 总结:自定义 Collector 的 5 个核心方法
    • ✅ Collector 特性(`characteristics()`)常见值

324. Java Stream API - 实现Collector接口:自定义你的流式收集器

在 Java Stream API 中,Collector是终端操作collect()背后的核心接口。如果你希望完全掌控数据收集的过程——比如构造特定的数据结构、在并行流中定制合并方式等——那就需要了解如何实现这个接口。


🔍 为什么要实现Collector接口?

虽然大多数时候我们可以使用 Java 提供的标准收集器(如toList()groupingBy()joining()),但当你需要:

  • 创建一个自定义结构(如:合并值到一个特殊格式的字符串、构造非标准 Map 等)
  • 控制并行流合并逻辑(比如收集到线程安全容器)
  • 优化性能(跳过不必要的转换)

那么实现Collector接口就是最灵活且强大的方式。


☕ 自定义 Collector 的三种方式

方法描述适用场景
✅ 使用Collectors工厂方法组合已有收集器,或配合collectingAndThen()做轻度自定义推荐优先使用
✅ 使用Stream.collect(supplier, accumulator, combiner)自行传入构造、累加与合并逻辑中等灵活性
✅❗ 实现Collector<T, A, R>接口完全掌控所有阶段,适合高度定制最灵活,但技术门槛高

📐 理解Collector<T, A, R>的三个类型参数

我们先看一下接口定义:

interfaceCollector<T,A,R>{...}
  • T:流中元素的类型
  • A:中间可变容器类型(Accumulator 类型)
  • R:最终返回结果类型(Result 类型)

🚗 举例说明

收集器T(流中元素)A(中间容器)R(最终结果)
toList()StringArrayList<String>List<String>
toSet()StringHashSet<String>Set<String>
groupingBy(String::length, counting())String内部 Map + CounterMap<Integer, Long>

➡️ 注意:我们平时用Collectors.toList()等时,看不到A的具体类型,是因为返回类型中对它进行了隐藏(用?代替了)。


📋 代码示例:查看Collector类型参数

Collection<String>strings=List.of("two","three","four","five","six","seven","eight","nine","ten","eleven","twelve");// toListCollector<String,?,List<String>>listCollector=Collectors.toList();List<String>list=strings.stream().collect(listCollector);System.out.println("Size of list = "+list.size());// 11// toSetCollector<String,?,Set<String>>setCollector=Collectors.toSet();Set<String>set=strings.stream().collect(setCollector);System.out.println("Size of set = "+set.size());// 11// groupingBy + countingCollector<String,?,Map<Integer,Long>>groupingCollector=Collectors.groupingBy(String::length,Collectors.counting());Map<Integer,Long>map=strings.stream().collect(groupingCollector);System.out.println("Size of map = "+map.size());// 4

这些例子中,?代表我们无需关心中间类型 A——由 API 实现者决定,我们只关心结果类型 R。


🧪 补充示例:自定义 Collector 实现(首字母统计)

我们实现一个 collector,用于按单词首字母统计出现次数:

classFirstLetterCountCollectorimplementsCollector<String,Map<Character,Integer>,Map<Character,Integer>>{@OverridepublicSupplier<Map<Character,Integer>>supplier(){returnHashMap::new;}@OverridepublicBiConsumer<Map<Character,Integer>,String>accumulator(){return(map,word)->{charfirst=word.charAt(0);map.merge(first,1,Integer::sum);};}@OverridepublicBinaryOperator<Map<Character,Integer>>combiner(){return(map1,map2)->{map2.forEach((k,v)->map1.merge(k,v,Integer::sum));returnmap1;};}@OverridepublicFunction<Map<Character,Integer>,Map<Character,Integer>>finisher(){returnFunction.identity();// 直接返回中间容器}@OverridepublicSet<Characteristics>characteristics(){returnSet.of(Characteristics.IDENTITY_FINISH);}}

使用:

List<String>words=List.of("apple","apricot","banana","blueberry","cherry");Map<Character,Integer>counts=words.stream().collect(newFirstLetterCountCollector());System.out.println(counts);// {a=2, b=2, c=1}

🧠 总结:自定义 Collector 的 5 个核心方法

方法作用
supplier()创建中间结果容器
accumulator()累加流中的每个元素
combiner()并行流中合并两个中间结果
finisher()将中间容器转换为最终结果
characteristics()提供 collector 的特性,如是否为并发、安全等

✅ Collector 特性(characteristics())常见值

特性说明
CONCURRENT支持并发(accumulator 线程安全)
UNORDERED不依赖顺序(如 Set 类型)
IDENTITY_FINISHAR类型相同,finisher()可直接返回
http://www.jsqmd.com/news/383785/

相关文章:

  • Seedance 2.0多镜头一致性配置全链路拆解:从标定误差归因到时序同步调优,3类致命配置陷阱避坑手册
  • AI助手专业能力评估实战:构建多维度Agent Skills度量体系
  • 构建未来教育新生态:智慧校园平台方案关键模块建设浅析
  • 2026年,银川口碑搬家公司推荐:行业分析+避坑指南+尖兵搬家全解析 - 宁夏壹山网络
  • 【Seedance 2.0多镜头一致性逻辑调优白皮书】:20年视觉算法专家亲授3大瓶颈突破法+实测性能提升47.8%关键路径
  • Seedance 2.0多镜头一致性逻辑性能翻倍指南:5个被90%团队忽略的GPU内存对齐技巧与帧同步时序优化
  • [论文阅读] AI + 软件工程 | 33k+ AI编码PR实证揭秘:为什么AI提交的代码常被拒绝?深度解析:原理、实战与踩坑记录
  • 【Seedance 2.0多镜头一致性权威指南】:20年视觉算法专家亲授5步精准配置法,97%用户首次部署即通过一致性校验
  • SiameseUIE中文-base实战手册:从CSDN GPU Pod访问到Web界面全链路验证
  • 【Seedance 2.0 多镜头一致性逻辑 API 权威指南】:20年CV架构师亲授工业级跨视角协同推理设计心法
  • 【高精度气象】2026气象功率预测:多源数据越多越乱?一致性约束+自动降级,企业级稳定的最后一道防线
  • AI头像生成器企业落地:为SaaS产品嵌入头像创意生成模块技术路径
  • RexUniNLU中文NLP模型体验:电商评论情感分析实战案例
  • Qwen2.5-32B-Instruct保姆级教程:从安装到生成第一篇文章
  • 中小型企业健身房设备清单:拒绝冗余,上海皓衍精准适配更省心 - 冠顶工业设备
  • 『NAS』B站油管视频一键下载-MeTube
  • nvm安装Node后node -v正常,npm -v提示“无法加载文件”问题应对
  • AI赋能内容转化:小说转短剧实操全流程(零编程基础适配)
  • AI赋能内容创作:从零开始,将小说高效改编为短剧
  • 2026年2月大庆整装装修公司推荐榜,彰显本地服务实力 - 品牌鉴赏师
  • 2026年2月北京石景山区老年院权威推荐,口碑排行与真实评价汇总! - 品牌鉴赏师
  • Web 后台开发还能这么快?XinServer 震惊我
  • 重新定义“轻松”:一个轻量级框架,XXL-JOB,如何承载企业级分布式任务调度?
  • 通义千问多模态重排序:图片搜索从此大不同
  • CCF GESP C++讲义和真题汇总5级完整版(学生版) 【from 黄老师】
  • SenseVoice-Small ONNX部署教程:Kubernetes集群中轻量级Pod编排
  • Qwen3-TTS-Tokenizer-12Hz多场景:适配Whisper/Paraformer等ASR前端
  • Qwen2.5-7B-Instruct业务赋能:SaaS产品客户支持知识库构建
  • [特殊字符] SDXL 1.0 电影级绘图工坊:5分钟快速上手AI绘画,零基础也能玩转
  • 超参数优化组件:从黑盒调优到可解释工程化实践