发布于2026-07-08 阅读(0)
扫一扫,手机访问
要实现一个自定义的 Collector,本质上就是提供四个关键组件:supplier(容器怎么建)、accumulator(元素怎么往里塞)、combiner(并行时怎么合并)、finisher(最后怎么转成想要的结果),再顺手声明一下特征(characteristics)就完事了。听起来步骤清晰,但真上手写的时候,细节上容易踩坑。

第一步,得先想清楚你到底要收集成什么结果。比如要去重后拼个字符串?还是分组统计?或者构建一个自定义对象?目标不同,中间容器的类型就跟着变。举个实际例子,如果你要做不重复的字符串拼接,中间容器用 LinkedHashSet 就很合适——既能保证顺序,又能天然去重。要是想统计频次,HashMap 就是标配。
通过 Collector.of() 这个静态工厂方法,把四个函数依次传进去就行了:
() -> new LinkedHashSet<>(),每次调用都新建一个空容器。(set, item) -> set.add(item),把流里的每个元素塞进容器里。(set1, set2) -> { set1.addAll(set2); return set1; },合并两个中间容器——注意只有并行流才会用到这个方法。set -> String.join(",", set),把最终的容器转成你想要的结果类型。有一个小窍门:如果 finisher 其实是恒等函数(比如 Function.identity()),那直接省略就行,此时 Collector 返回的就是中间容器本身。
最后一个参数是一个 Set,里面可以选几个常见的特征标记:
CONCURRENT:表示 accumulator 支持多线程安全调用(比如你用了 ConcurrentHashMap),此时 supplier 必须返回同一个共享实例——但坦率讲,一般不建议这么搞,容易翻车。UNORDERED:表示收集结果不依赖流中元素的原始顺序(比如统计总数、求最大值),开启这个标记可以提升并行性能。IDENTITY_FINISH:表示 finisher 是恒等操作,框架可以跳过转换步骤,少一次函数调用。大多数自定义 Collector 不会设 CONCURRENT,而是老老实实靠 combiner 来合并——这种做法更安全、也更通用。
写完之后,直接在 stream 后面调用 collect(yourCollector) 就能用了。不过建议你至少做两轮测试:
list1.addAll(list2); return list2;,那结果就会把一部分数据弄丢,这种低级错误很容易犯。整体来说,自定义 Collector 算不上复杂,但每个环节的细节都值得花点心思,尤其是并行场景下的合并逻辑。
下一篇:如何通过yum排除特定软件包
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8