Spliterator:为并行处理进行拆分
实现自定义 Spliterator,将领域数据公开为可拆分的流来源
Spliterator:为并行处理进行拆分 是 CoddyKit 上的免费 Java Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Java Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Java Academy 课程共包含 4 节课。
什么是 Spliterator
Spliterator(可拆分迭代器)是流背后的核心机制。它可以迭代元素,并将自身拆分为两部分以进行并行处理。
Spliterator 的关键方法
四个核心方法分别是:tryAdvance(处理一个元素)、forEachRemaining(处理所有剩余元素)、trySplit(拆分为两部分)和 estimateSize(估算元素数量)。
Spliterator<Integer> sp = List.of(1,2,3,4,5,6).spliterator();
Spliterator<Integer> half = sp.trySplit(); // splits off first ~half
half.forEachRemaining(System.out::println); // 1 2 3
sp.forEachRemaining(System.out::println); // 4 5 6Spliterator 的特征
Spliterator 使用位标志声明自身的特征:SIZED、ORDERED、DISTINCT、SORTED、NONNULL、IMMUTABLE、CONCURRENT、SUBSIZED。
Spliterator<String> sp = List.of("a","b","c").spliterator();
System.out.println(Integer.toBinaryString(sp.characteristics()));
// Characteristics include ORDERED, SIZED, SUBSIZEDtrySplit 的工作方式
trySplit() 会返回一个新的 Spliterator,大致覆盖剩余元素的一半。原 Spliterator 则覆盖另一半。如果无法拆分,请返回 null。
// ArrayList Spliterator splits efficiently at midpoint:
// [0,1,2,3,4,5] -> [0,1,2] (new) + [3,4,5] (original)构建自定义 Spliterator
实现 Spliterator<T>,即可将自定义数据结构作为流源公开出来。请定义 trySplit 以启用并行处理。
public class RangeSpliterator implements Spliterator<Integer> {
private int start, end;
public RangeSpliterator(int start, int end) { this.start=start; this.end=end; }
public boolean tryAdvance(Consumer<? super Integer> action) {
if (start >= end) return false;
action.accept(start++); return true;
}
public Spliterator<Integer> trySplit() {
int mid = (start + end) / 2;
if (mid <= start) return null;
RangeSpliterator prefix = new RangeSpliterator(start, mid);
this.start = mid; return prefix;
}
public long estimateSize() { return end - start; }
public int characteristics() { return ORDERED | SIZED | SUBSIZED | IMMUTABLE; }
}从 Spliterator 创建流
使用 StreamSupport.stream(spliterator, parallel) 从任意 spliterator 创建流。它连接了自定义数据源与 Stream API。
Spliterator<Integer> sp = new RangeSpliterator(0, 1_000_000);
Stream<Integer> stream = StreamSupport.stream(sp, true); // true = parallel
long count = stream.filter(n -> n % 2 == 0).count();
System.out.println(count); // 500000二叉树的 Spliterator
自定义 Spliterator 可以让树等非列表结构支持并行处理。trySplit 会返回左子树的 spliterator,并保留右子树。
并行效率与拆分质量
并行流会递归拆分数据,直到每个数据块足够小,可以交给单个线程处理。高质量的拆分要求 estimateSize 准确,并且各个拆分部分的大小大致相等。
使用 forEachRemaining 进行批量处理
如果不需要拆分,请重写 forEachRemaining 来执行批量处理,从而避免在循环中反复调用 tryAdvance 所产生的逐元素开销。
@Override
public void forEachRemaining(Consumer<? super Integer> action) {
for (int i = start; i < end; i++) action.accept(i);
start = end; // mark as exhausted
}Spliterator 与迭代器的比较
Iterator:仅支持顺序处理,没有大小提示,也不能拆分。Spliterator:支持并行处理,提供特征和大小估算,并且专为 Stream API 设计。
快速检查
无法拆分时,trySplit() 会返回什么?
回顾
Spliterator 是并行流的引擎。实现 tryAdvance、trySplit、estimateSize 和 characteristics,即可将自定义数据结构公开为流。使用 StreamSupport.stream(sp, true) 即可启用并行处理。
常见问题解答
「Spliterator:为并行处理进行拆分」课时是免费的吗?
是的 — 「Spliterator:为并行处理进行拆分」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Java Academy 课程的其余内容,请升级到 CoddyKit PRO。 Java Academy 课程共包含 4 节课。
「Spliterator:为并行处理进行拆分」这节课中我会学到什么?
实现自定义 Spliterator,将领域数据公开为可拆分的流来源 你通过在浏览器中直接运行的动手代码来练习 Java Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Java Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Java Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。
「Spliterator:为并行处理进行拆分」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Java Academy 课中编写并运行代码吗?
能。每节 Java Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 用于嵌套集合的 flatMap
- 并行流:性能与陷阱
- Spliterator:为并行处理进行拆分
- 使用 iterate 和 generate 创建无限流