spliterator 是为并行设计的专用工具,解决能否拆、剩多少、如何安全高效拆分三大问题;其 trysplit() 支持分割、characteristics() 影响并行行为决策、estimatesize() 决定任务粒度与调度效率。

Spliterator 不是 Iterator 的升级版,而是为并行而生的专用工具。Iterator 只管“一个接一个往下走”,它回答不了并行流最关心的三个问题:还能不能拆?剩下多少?怎么拆才安全高效?Spliterator 把这三个问题全包了。
trySplit() 是并行拆分的开关
Iterator 没有分割能力,一旦用它构造 parallelStream(比如 StreamSupport.stream(iterator, true)),并行流会直接退化成单线程执行——因为根本切不开。
- trySplit() 成功时返回一个新的 Spliterator,原对象自动代表“剩下的部分”,两者覆盖范围互斥且合起来不遗漏
- 返回 null 不是出错,而是明确告诉框架:“别再切了,我这整块自己干完”
- ArrayList 的 trySplit() 按索引均分,效率高;LinkedList 基本返回 null,所以对它用 parallelStream 几乎没提速
characteristics() 决定并行行为是否合理
这个方法返回一组位标识,Stream API 靠它做关键决策,比如要不要保序、需不需要加锁、能不能跳过空值检查。
- 带 ORDERED 特征(如 ArrayList、数组):forEachOrdered() 才能保证顺序;HashSet 没这个特征,并行遍历时顺序不可预期
- 含 CONCURRENT(如 ConcurrentHashMap):底层已线程安全,Spliterator 可能选择不分割,避免额外开销
- 有 SIZED + SUBSIZED(如 ArrayList):estimateSize() 返回准确值,拆分容易做到负载均衡;LinkedList 缺少 SIZED,估算常为 Long.MAX_VALUE 或 0,调度器不敢轻易分派任务
estimateSize() 影响任务粒度和调度效率
它不是必须精确,但严重偏离会影响并行效果:估得太小,产生大量细碎任务,线程调度开销压倒计算收益;估得太大,线程数上不去,硬件资源浪费。
- ArrayList 的 estimateSize() 返回真实 size,拆分策略倾向二分,适合 fork/join 动态平衡
- 自定义 Spliterator 若返回 Long.MAX_VALUE,ForkJoinPool 可能过度保守,迟迟不启动子任务
- 对动态数据源(如日志文件流),返回 Long.MAX_VALUE 是常见且合理的妥协
你不需要手写 Spliterator,但选对集合类型就是在调用它的能力。ArrayList 天然适配并行,LinkedList 基本不参与,ConcurrentHashMap 则走另一套并发友好路径——理解这些,比调 parallelStream() 的参数更管用。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











