自定义 Collector 的核心是实现其五个方法,但推荐使用 Collector.of()——它更安全简洁且自动处理并发与异常;Collector 是三型参接口,含 supplier、accumulator、combiner、finisher 四组件及 characteristics 特征。

自定义 Collector 的核心在于实现 Collector 接口的五个方法,但更推荐使用 Collector.of() 静态工厂方法——它更安全、简洁,且能自动处理并发与异常场景。
理解 Collector 的四个关键组件
Collector 是一个三型参泛型接口:
- T:流中元素的类型(输入)
-
A:可变累积容器的类型(中间结果,如
StringBuilder、ArrayList、自定义类) - R:最终收集结果的类型(输出,可以和 A 相同,也可以不同)
它由四部分组成:supplier(供应器)、accumulator(累加器)、combiner(合并器)、finisher(终结器),外加一个 characteristics(特征) 告诉 Stream 是否支持并行、是否无序、是否是 IDENTITY_FINISH 等。
用 Collector.of() 快速创建线程安全的自定义收集器
这是最常用也最推荐的方式。例如:把字符串流拼接成用分号隔开、首尾带括号的格式,如 "(a;b;c)":
Collector<string stringbuilder string> bracketedSemicolonJoiner =
Collector.of(
() -> new StringBuilder("("), // supplier:初始化容器
(sb, s) -> sb.append(s).append(";"), // accumulator:每次追加元素和分号
(sb1, sb2) -> sb1.append(sb2.substring(1)), // combiner:合并两个 StringBuilder(去掉 sb2 开头的 "(")
sb -> sb.deleteCharAt(sb.length() - 1).append(")")) // finisher:删掉末尾多余分号,补右括号
);</string>
注意:combiner 的逻辑必须与 accumulator 一致且可结合;这里假设每个 StringBuilder 都以 "(" 开头,所以合并时跳过 sb2 的第一个字符。
支持并行时必须提供 combiner 并声明 CONCURRENT 特性
如果希望收集器在并行流中正确工作,需满足两点:
- 提供非空的
combiner函数 - 在
characteristics中包含Collector.Characteristics.CONCURRENT
例如:统计字符串流中各单词出现次数,并保证并行安全:
Collector<string map integer>, Map<string integer>> wordCountCollector =
Collector.of(
HashMap::new,
(map, word) -> map.merge(word.toLowerCase(), 1, Integer::sum),
(m1, m2) -> {
m2.forEach((k, v) -> m1.merge(k, v, Integer::sum));
return m1;
},
Function.identity(),
Collector.Characteristics.CONCURRENT // ⚠️ 关键:声明并发友好
);</string></string>
此时可放心用于 parallelStream().collect(wordCountCollector)。
封装成可复用的工具类(带参数化)
把逻辑提取为静态方法,支持灵活配置。比如一个通用的「带前缀/后缀/分隔符」连接器:
public static Collector<charsequence string> joining(
CharSequence prefix, CharSequence delimiter, CharSequence suffix) {
return Collector.of(
() -> new StringJoiner(delimiter, prefix, suffix),
(joiner, cs) -> joiner.add(cs),
StringJoiner::merge,
StringJoiner::toString
);
}
<p>// 使用:
List<string> list = Arrays.asList("a", "b", "c");
String result = list.stream().collect(joining("[", ", ", "]")); // "[a, b, c]"
</string></p></charsequence>
这里复用了 JDK 的 StringJoiner,它的 merge 方法已内置线程安全合并逻辑,且 toString 就是自然的 finisher。
不复杂但容易忽略的是:collector 的语义必须保持一致——supplier 初始化的容器,在 accumulator 和 combiner 中要按同一规则更新,finisher 才能可靠产出结果。写完建议用串行和并行流各测一次,尤其关注空流、单元素、多线程混合场景。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











