私はすでにこれとこのStream.skip
質問を読みましたが、観測された動作がJDKの作成者によって意図されたものであるかどうかはまだ疑問です.
1..20 の数字を簡単に入力してみましょう:
List<Integer> input = IntStream.rangeClosed(1, 20).boxed().collect(Collectors.toList());
unordered()
次に、並列ストリームを作成しskip()
、さまざまな方法で を組み合わせて、結果を収集しましょう。
System.out.println("skip-skip-unordered-toList: "
+ input.parallelStream().filter(x -> x > 0)
.skip(1)
.skip(1)
.unordered()
.collect(Collectors.toList()));
System.out.println("skip-unordered-skip-toList: "
+ input.parallelStream().filter(x -> x > 0)
.skip(1)
.unordered()
.skip(1)
.collect(Collectors.toList()));
System.out.println("unordered-skip-skip-toList: "
+ input.parallelStream().filter(x -> x > 0)
.unordered()
.skip(1)
.skip(1)
.collect(Collectors.toList()));
ここでは、フィルタリング ステップは基本的に何もしませんが、ストリーム エンジンの処理がさらに難しくなります。現在、出力の正確なサイズがわからないため、一部の最適化がオフになっています。次の結果があります。
skip-skip-unordered-toList: [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
// absent values: 1, 2
skip-unordered-skip-toList: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 18, 19, 20]
// absent values: 1, 15
unordered-skip-skip-toList: [1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 19, 20]
// absent values: 7, 18
結果はまったく問題なく、すべてが期待どおりに機能します。最初のケースでは、最初の 2 つの要素をスキップしてから、特定の順序でリストに収集するように依頼しました。2 番目のケースでは、最初の要素をスキップするように依頼し、次に unordered に変えて、もう 1 つの要素をスキップするように依頼しました (どの要素かは気にしません)。3 番目のケースでは、最初に順不同モードになり、次に任意の 2 つの要素をスキップしました。
1 つの要素をスキップして、非順序モードでカスタム コレクションに収集しましょう。カスタム コレクションは次のようになりますHashSet
。
System.out.println("skip-toCollection: "
+ input.parallelStream().filter(x -> x > 0)
.skip(1)
.unordered()
.collect(Collectors.toCollection(HashSet::new)));
出力は満足のいくものです:
skip-toCollection: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
// 1 is skipped
したがって、一般に、ストリームが順序付けられている限りskip()
、最初の要素をスキップし、それ以外の場合は任意の要素をスキップすることを期待しています。
ただし、同等の順序付けられていない端末操作を使用しましょうcollect(Collectors.toSet())
。
System.out.println("skip-toSet: "
+ input.parallelStream().filter(x -> x > 0)
.skip(1)
.unordered()
.collect(Collectors.toSet()));
出力は次のようになります。
skip-toSet: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15, 16, 17, 18, 19, 20]
// 13 is skipped
他の順序付けられていない端末操作 ( 、 、 など) でも同じ結果が得forEach
られfindAny
ますanyMatch
。この場合、ステップを削除unordered()
しても何も変わりません。stepunordered()
は現在の操作からストリームを正しく順不同にしますが、順不同の端末操作は、skip()
使用された場合に結果に影響を与える可能性があるにもかかわらず、最初からストリーム全体を順不同にします。これは私にとって完全に誤解を招くようです: unordered コレクターを使用することは、端末操作の直前にストリームを unordered モードにして、同等の ordered コレクターを使用することと同じだと思います。
だから私の質問は:
- この動作は意図されたものですか、それともバグですか?
- はいの場合、それはどこかに文書化されていますか?Stream.skip()のドキュメントを読みました。順序付けられていない端末操作については何も述べていません。また、Characteristics.UNORDEREDのドキュメントはあまり理解されておらず、ストリーム全体で順序付けが失われるとは述べていません。最後に、パッケージ概要の注文セクションもこのケースをカバーしていません。おそらく私は何かが欠けていますか?
- 順序付けされていない端末操作によってストリーム全体が順序付けされていないことが意図されている場合、なぜ
unordered()
step がこの時点以降だけ順序付けされないようにするのですか? この動作に頼ることができますか? それとも、最初のテストがうまく機能しただけで幸運でしたか?