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

文章目录

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

我们先看一下接口定义:

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

🚗 举例说明

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

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


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

java 复制代码
Collection<String> strings = List.of(
    "two", "three", "four", "five", "six", "seven", "eight", "nine",
    "ten", "eleven", "twelve"
);

// toList
Collector<String, ?, List<String>> listCollector = Collectors.toList();
List<String> list = strings.stream().collect(listCollector);
System.out.println("Size of list = " + list.size()); // 11

// toSet
Collector<String, ?, Set<String>> setCollector = Collectors.toSet();
Set<String> set = strings.stream().collect(setCollector);
System.out.println("Size of set = " + set.size()); // 11

// groupingBy + counting
Collector<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,用于按单词首字母统计出现次数:

java 复制代码
class FirstLetterCountCollector implements Collector<String, Map<Character, Integer>, Map<Character, Integer>> {

    @Override
    public Supplier<Map<Character, Integer>> supplier() {
        return HashMap::new;
    }

    @Override
    public BiConsumer<Map<Character, Integer>, String> accumulator() {
        return (map, word) -> {
            char first = word.charAt(0);
            map.merge(first, 1, Integer::sum);
        };
    }

    @Override
    public BinaryOperator<Map<Character, Integer>> combiner() {
        return (map1, map2) -> {
            map2.forEach((k, v) -> map1.merge(k, v, Integer::sum));
            return map1;
        };
    }

    @Override
    public Function<Map<Character, Integer>, Map<Character, Integer>> finisher() {
        return Function.identity(); // 直接返回中间容器
    }

    @Override
    public Set<Characteristics> characteristics() {
        return Set.of(Characteristics.IDENTITY_FINISH);
    }
}

使用:

java 复制代码
List<String> words = List.of("apple", "apricot", "banana", "blueberry", "cherry");

Map<Character, Integer> counts = words.stream()
    .collect(new FirstLetterCountCollector());

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_FINISH AR 类型相同,finisher() 可直接返回
相关推荐
H Corey2 小时前
数据结构与算法:高效编程的核心
java·开发语言·数据结构·算法
独行soc2 小时前
2026年渗透测试面试题总结-24(题目+回答)
网络·python·安全·web安全·渗透测试·安全狮
米羊1212 小时前
Struts 2 漏洞(上)
java·后端·struts
SmartBrain2 小时前
Python 特性(第一部分):知识点讲解(含示例)
开发语言·人工智能·python·算法
Lun3866buzha2 小时前
基于YOLO11-C3k2-FFCM:跳甲虫害叶片智能检测与识别系统
python
galaxyffang2 小时前
Java堆内存诊断:从工具使用到实战分析
java·jvm
Gaosiy2 小时前
技术细节-MNE读取neuroscan curry9版本cdt文件
python·脑机接口·脑电·mne
非凡ghost3 小时前
小X分身APP(手机分身类工具)
android·windows·学习·智能手机·软件需求
SmartBrain3 小时前
FastAPI进阶(第一部分):路由和依赖特性(含考题)
开发语言·python