私が書いているライブラリの低レベルの操作に直接ストリームスプリッターを使用しています。最近、ストリームスプリッターを使用して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
ご覧のとおり、フラットマッピングの後、から1
までの連続した番号の順序付けられたストリームを取得する必要があり9
ます。スプリテレーターを1回分割したので、中間の場所にジャンプするはずです。次に、その要素を使用して、もう一度分割します。その後、残りのすべての要素を印刷します。ストリームテールからいくつかの連続した要素があると思います(おそらくゼロ要素ですが、それでも問題ありません)。しかし、私が得るものは5
、そして6
、突然ジャンプし9
ます。
私は現在、JDKのスプリテレーターがこのように使用されていないことを知っています。これらは常に走査の前に分割されます。ただし、公式ドキュメントでは、明示的にtrySplit
after を呼び出すことを禁止していませんtryAdvance
。
コレクション、配列、生成されたソースなどから直接作成されたスプリッターを使用した場合、この問題は見られませんでした。この問題は、スプリッターが中間の並列ストリームから作成された場合にのみ観察されましたflatMap
。
だから問題は、私はバグにぶつかったのか、それともこの方法でスプリッターを使用することが明示的に禁止されているのか?
AbstractWrappingSpliterator
と会社のソースから見ることができるものから、あなたtryAdvance
がの場合、flatMap
(4,5,6)の出力はバッファーに入れられ、その後4が消費されて(5,6)がバッファーに残ります。次に、trySplit
正しく(7,8)を新しいものに分割しSpliterator
、9を古いものに残しますが、バッファリングされた(5,6)は古いままSpliterator
です。
これはバグのようです。バッファを新しいものに渡すか、バッファが空でない場合はSpliterator
戻りnull
、分割を拒否する必要があります。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加