一見簡単ではないスプリッテレータに関する質問です。
ストリームで.parallel()
は、ストリームが処理される動作を変更します。ただし、順次ストリームと並列ストリームから作成されたスプリッテレータは同じであると予想していました。たとえば、通常、順次ストリームで.trySplit()
は が呼び出されることはありませんが、並列ストリームではスプリット スプリッテレータを別のスレッドに渡すために呼び出されます。
stream.spliterator()
vsの違いstream.parallel().spliterator()
:
それらには異なる特性がある場合があります。
Stream.of(1L, 2L, 3L).limit(2); // ORDERED Stream.of(1L, 2L, 3L).limit(2).parallel(); // SUBSIZED, SIZED, ORDERED
ここで説明されている別のナンセンスなストリームスプリッター特性ポリシー(並行して計算された方が良いようです)のようです:Java 8およびJava 9でのスプリッテレーター特性の理解
を使用した分割に関して、それらは異なる動作をする場合があります
.trySplit()
。Stream.of(1L, 2L, 3L); // NON NULL Stream.of(1L, 2L, 3L).limit(2); // NULL Stream.of(1L, 2L, 3L).limit(2).parallel(); // NON NULL
最後の 2 つの動作が異なるのはなぜですか? シーケンシャル ストリームを分割したいのに分割できないのはなぜですか? (たとえば、高速処理のために分割の 1 つを破棄すると便利な場合があります)。
スプリッテレータをストリームに変換するときの大きな影響:
spliterator = Stream.of(1L, 2L, 3L).limit(2).spliterator(); stream = StreamSupport.stream(spliterator, true); // No parallel processing!
この場合、スプリッテレータは分割機能を無効にするシーケンシャル ストリームから作成されました ( .trySplit()
null を返します)。後でストリームに戻す必要がある場合、そのストリームは並列処理の恩恵を受けません。残念なこと。
大きな問題:回避策として、呼び出す前に常にストリームを並列に変換することの主な影響は何ですか?.spliterator()
// Supports activation of parallel processing later
public static <T> Stream<T> myOperation(Stream<T> stream) {
boolean isParallel = stream.isParallel();
Spliterator<T> spliterator = stream.parallel().spliterator();
return StreamSupport.stream(new Spliterator<T>() {
// My implementation of the interface here (omitted for clarity)
}, isParallel).onClose(stream::close);
}
// Now I have the option to use parallel processing when needed:
myOperation(stream).skip(1).parallel()...