【发布时间】:2019-04-02 20:22:03
【问题描述】:
在查看WrappingSpliterator::trySplit 的源代码时,我被它的实现误导了:
@Override
public Spliterator<P_OUT> trySplit() {
if (isParallel && buffer == null && !finished) {
init();
Spliterator<P_IN> split = spliterator.trySplit();
return (split == null) ? null : wrap(split);
}
else
return null;
}
如果您想知道为什么这很重要,例如是因为:
Arrays.asList(1,2,3,4,5)
.stream()
.filter(x -> x != 1)
.spliterator();
正在使用它。据我了解,向流中添加任何中间操作都会导致该代码被触发。
基本上,这种方法说除非流是并行的,否则将这个 Spliterator 视为根本无法拆分的。这对我很重要。在我的一种方法中(这就是我获得该代码的方式),我得到一个Stream 作为输入,并使用trySplit 手动将其“解析”成更小的部分。例如,您可以认为我正在尝试从Stream 执行findLast。
这就是我想要分裂成更小块的愿望的地方,因为只要我这样做:
Spliterator<T> sp = stream.spliterator();
Spliterator<T> prefixSplit = sp.trySplit();
我发现prefixSplit 是null,这意味着除了用forEachRemaning 消耗整个sp 之外,我基本上无能为力。
这有点奇怪,可能当filter 出现时它是有意义的;因为在这种情况下(在我的理解中)可以返回Spliterator 的唯一方法是使用某种buffer,甚至可能具有预定义的大小(很像Files::lines)。但为什么会这样:
Arrays.asList(1,2,3,4)
.stream()
.sorted()
.spliterator()
.trySplit();
返回null 是我不明白的。 sorted 是一种有状态的操作,它无论如何都会缓冲元素,而不会实际减少或增加它们的初始数量,所以至少理论上这可以返回 null 以外的东西...
【问题讨论】:
-
嗯...可能是因为流不并行?明显的问题......你试过
Arrays.asList(1,2,3,4).parallelStream()......吗? -
@FedericoPeraltaSchaffner 当然... :) 但是如果您删除
filter并且流也不是并行的,则拆分将起作用。文档没有说这必须发生在并行流中。 -
from javadoc: *
此方法可能因任何原因返回{@code null},*包括空虚、遍历开始后无法拆分、数据结构约束和效率*注意事项。
-
当您不链接中间操作时,
spliterator()将只返回源拆分器,即Arrays.asList(1,2,3,4,5) .stream() .spliterator() .getClass() == Arrays.spliterator(new Integer[] { 1,2,3,4,5 }) .getClass()。这样的拆分器甚至不知道 Stream 是否是并行的,或者 Stream 是否存在。不,Arrays.asList(1,2,3,4,5) .parallelStream() .filter(x -> x != 1) .spliterator();不需要需要任何缓冲。 -
@Holger 对,我已经看到如果没有中间操作,则返回源拆分器,即使是
WrappingSpliterator通过spliteratorSupplier“知道”它。第二点是我认为它可能是用缓冲区实现的,我现在查看了实现,你是对的,它拆分了源拆分器......所以在这种情况下的问题是这是对顺序流的深思熟虑的决定吗?你知道这其中的原因吗?谢谢
标签: java java-8 java-stream