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

📅 发布时间:2026/7/5 18:59:38 👁️ 浏览次数:
324. Java Stream API - 实现 Collector 接口:自定义你的流式收集器
文章目录324. Java Stream API - 实现 Collector 接口自定义你的流式收集器 为什么要实现 Collector 接口☕ 自定义 Collector 的三种方式 理解 CollectorT, 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)自行传入构造、累加与合并逻辑中等灵活性✅❗ 实现CollectorT, A, R接口完全掌控所有阶段适合高度定制最灵活但技术门槛高 理解CollectorT, A, R的三个类型参数我们先看一下接口定义interfaceCollectorT,A,R{...}T流中元素的类型A中间可变容器类型Accumulator 类型R最终返回结果类型Result 类型 举例说明收集器T流中元素A中间容器R最终结果toList()StringArrayListStringListStringtoSet()StringHashSetStringSetStringgroupingBy(String::length, counting())String内部 Map CounterMapInteger, Long➡️ 注意我们平时用Collectors.toList()等时看不到A的具体类型是因为返回类型中对它进行了隐藏用?代替了。 代码示例查看Collector类型参数CollectionStringstringsList.of(two,three,four,five,six,seven,eight,nine,ten,eleven,twelve);// toListCollectorString,?,ListStringlistCollectorCollectors.toList();ListStringliststrings.stream().collect(listCollector);System.out.println(Size of list list.size());// 11// toSetCollectorString,?,SetStringsetCollectorCollectors.toSet();SetStringsetstrings.stream().collect(setCollector);System.out.println(Size of set set.size());// 11// groupingBy countingCollectorString,?,MapInteger,LonggroupingCollectorCollectors.groupingBy(String::length,Collectors.counting());MapInteger,Longmapstrings.stream().collect(groupingCollector);System.out.println(Size of map map.size());// 4这些例子中?代表我们无需关心中间类型 A——由 API 实现者决定我们只关心结果类型 R。 补充示例自定义 Collector 实现首字母统计我们实现一个 collector用于按单词首字母统计出现次数classFirstLetterCountCollectorimplementsCollectorString,MapCharacter,Integer,MapCharacter,Integer{OverridepublicSupplierMapCharacter,Integersupplier(){returnHashMap::new;}OverridepublicBiConsumerMapCharacter,Integer,Stringaccumulator(){return(map,word)-{charfirstword.charAt(0);map.merge(first,1,Integer::sum);};}OverridepublicBinaryOperatorMapCharacter,Integercombiner(){return(map1,map2)-{map2.forEach((k,v)-map1.merge(k,v,Integer::sum));returnmap1;};}OverridepublicFunctionMapCharacter,Integer,MapCharacter,Integerfinisher(){returnFunction.identity();// 直接返回中间容器}OverridepublicSetCharacteristicscharacteristics(){returnSet.of(Characteristics.IDENTITY_FINISH);}}使用ListStringwordsList.of(apple,apricot,banana,blueberry,cherry);MapCharacter,Integercountswords.stream().collect(newFirstLetterCountCollector());System.out.println(counts);// {a2, b2, c1} 总结自定义 Collector 的 5 个核心方法方法作用supplier()创建中间结果容器accumulator()累加流中的每个元素combiner()并行流中合并两个中间结果finisher()将中间容器转换为最终结果characteristics()提供 collector 的特性如是否为并发、安全等✅ Collector 特性characteristics()常见值特性说明CONCURRENT支持并发accumulator 线程安全UNORDERED不依赖顺序如 Set 类型IDENTITY_FINISHA与R类型相同finisher()可直接返回