gpt4 book ai didi

java - 并行流的 Stream.spliterator 的奇怪行为

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:55:34 26 4
gpt4 key购买 nike

我将流拆分器直接用于我正在编写的库中的低级操作。最近,当我进行流拆分器和交错 tryAdvance/trySplit 调用时,我发现了非常奇怪的行为。这是演示问题的简单代码:

import java.util.Arrays;
import java.util.Spliterator;

public class SpliteratorBug {
public static void main(String[] args) {
Integer[][] input = { { 1 }, { 2, 3 }, { 4, 5, 6 }, { 7, 8 }, { 9 } };
Spliterator<Integer> spliterator = Arrays.stream(input).parallel()
.flatMap(Arrays::stream).spliterator();
spliterator.trySplit();
spliterator.tryAdvance(s -> {});
spliterator.trySplit();
spliterator.forEachRemaining(System.out::println);
}
}

输出是

5
6
9

如您所见,在平面映射之后,我应该得到从 19 的连续数字的有序流。我拆分了一次拆分器,所以它应该跳到某个中间位置。接下来我从中消耗一个元素并再次拆分它。之后我打印所有剩余的元素。我希望我将有几个来自流尾的连续元素(可能是零个元素,也可以)。然而我得到的是 56,然后突然跳到 9

我知道目前在 JDK 中拆分器不是这样使用的:它们总是在遍历之前拆分。然而官方documentation没有明确禁止在 tryAdvance 之后调用 trySplit

当我使用直接从集合、数组、生成的源等创建的拆分器时,从未观察到该问题。只有当拆分器是从具有中间 flatMap 的并行流创建时才会观察到。

所以问题是:我是遇到了错误还是在某处明确禁止以这种方式使用拆分器?

最佳答案

来自 Spliterator.trySplit() 的文档:

This method may return null for any reason, including emptiness, inability to split after traversal has commenced, data structure constraints, and efficiency considerations.

(强调我的)

因此文档明确提到了在开始遍历后尝试拆分的可能性,并建议无法处理此问题的拆分器可能会返回 null

因此对于有序拆分器,观察到的行为应该被视为一个错误 as described by Misha .一般来说,trySplit() 必须返回一个 prefix 拆分器,换句话说,必须将所有关于下一个项目的中间状态移交给新的拆分器,这是Spliterator API 的一个特性,很可能会导致错误。我把这个问题作为检查我自己的拆分器实现的动机,并发现了一个类似的错误......

关于java - 并行流的 Stream.spliterator 的奇怪行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31152557/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com