回答:
あなたは間違った質問をしています。あなたは約求めているsequential
対parallel
あなたがアイテムを処理するのに対し、順番にあなたが尋ねるする必要がありますので、発注。順序付けられたストリームがあり、順序を維持することを保証する操作を実行する場合、ストリームが並列で処理されるか順次で処理されるかは関係ありません。実装は順序を維持します。
順序付けされたプロパティは、並列と順次とは異なります。たとえば、ストリームを呼び出すstream()
とHashSet
、ストリームは順序付けられず、呼び出しstream()
は順序付けられたストリームをList
返します。呼び出しunordered()
て注文契約を解除すると、パフォーマンスが向上する可能性があることに注意してください。ストリームに順序がない場合、順序を再確立する方法はありません。(順序付けられていないストリームを順序付けられたものに変える唯一の方法は、を呼び出すことsorted
ですが、結果の順序は必ずしも元の順序とは限りません)。
参照してください。「順序」セクションのjava.util.stream
パッケージのドキュメントを。
ストリーム操作全体を通して順序を確実に維持するには、ストリームのソース、すべての中間操作、およびターミナル操作のドキュメントを調べて、それらが順序を維持するかどうか(またはソースに最初の順序があるかどうか)を調べる必要があります。場所)。
これは非常に微妙な場合があります。たとえばStream.iterate(T,UnaryOperator)
、順序付けられたストリームをStream.generate(Supplier)
作成しながら、順序付けられていないストリームを作成します。順序を維持できないため、質問でもよくある間違いを犯したことに注意してください。ストリームの要素を保証された順序で処理する場合に使用する必要があります。forEach
forEachOrdered
したがってlist
、質問の内容が本当にであるjava.util.List
場合、そのstream()
メソッドは順序付けられたストリームを返し、順序をfilter
変更しません。したがって、を呼び出すとlist.stream().filter() .forEachOrdered()
、すべての要素が順番にlist.parallelStream().filter().forEachOrdered()
処理されますが、要素の場合は(フィルターなどによって)並列に処理される可能性がありますが、ターミナルアクションは順番に呼び出されます(並列実行の利点が明らかに低下します)。 。
たとえば、次のような操作を使用する場合
List<…> result=inputList.parallelStream().map(…).filter(…).collect(Collectors.toList());
操作全体で並列実行のメリットが得られる可能性がありますが、並列ストリームとシーケンシャルストリームのどちらを使用するかに関係なく、結果のリストは常に正しい順序になります。
List<>
順序を維持しますが、うCollection<>
?
Set
s SortedSet
またはでない限り、通常はありませんLinkedHashSet
。コレクションビューMap
(keySet()
、entrySet()
、およびvalues()
継承)Map
マップがあるときのポリシーは、つまりは、順序付けられSortedMap
たりLinkedHashMap
。動作は、コレクションのスプリッターで報告される特性によって決まります。のdefault
実装は特性をCollection
報告しないORDERED
ため、オーバーライドされない限り、順序付けされていません。
forEachOrdered
するforEach
場合とは異なるだけです。ただし、蒸し方が変わる場合に備えて、順序付けが重要な場合に使用することをお勧めします...
順序は、ソースデータ構造と中間ストリーム操作に依存します。あなたがList
処理を使用していると仮定すると、処理を注文する必要があります(filter
ここではシーケンスを変更しないため)。
S sequential()
Returns an equivalent stream that is sequential. May return itself, either because the stream was already sequential, or because the underlying stream state was modified to be sequential.
This is an intermediate operation.
S parallel()
Returns an equivalent stream that is parallel. May return itself, either because the stream was already parallel, or because the underlying stream state was modified to be parallel.
This is an intermediate operation.
S unordered()
Returns an equivalent stream that is unordered. May return itself, either because the stream was already unordered, or because the underlying stream state was modified to be unordered.
This is an intermediate operation.
ストリームには、定義されたエンカウンター順序がある場合とない場合があります。ストリームに遭遇順序があるかどうかは、ソースと中間操作に依存します。特定のストリームソース(Listや配列など)は本質的に順序付けられていますが、その他(HashSetなど)は順序付けされていません。Sorted()などの一部の中間操作では、その他の順序付けられていないストリームに遭遇順序を課すことがあり、その他の操作では、BaseStream.unordered()などの順序付けされたストリームを順序付けせずにレンダリングすることがあります。さらに、一部の端末操作では、forEach()などの遭遇順序が無視される場合があります。
ストリームが順序付けられている場合、ほとんどの操作は遭遇順に要素を操作するように制約されます。ストリームのソースが[1、2、3]を含むリストである場合、map(x-> x * 2)の実行結果は[2、4、6]でなければなりません。ただし、ソースに定義された遭遇順序がない場合、値[2、4、6]の順列は有効な結果になります。
順次ストリームの場合、エンカウンター順序の有無はパフォーマンスには影響せず、決定論にのみ影響します。ストリームが順序付けられている場合、同じソースで同じストリームパイプラインを繰り返し実行すると、同じ結果が生成されます。順序付けされていない場合、繰り返し実行すると異なる結果が生じる可能性があります。
並列ストリームの場合、順序付けの制約を緩和すると、より効率的な実行が可能になる場合があります。重複のフィルタリング(distinct())やグループ化された削減(Collectors.groupingBy())などの特定の集約操作は、要素の順序が関係ない場合により効率的に実装できます。同様に、limit()など、本質的にエンカウンターの順序に関連付けられている操作では、適切な順序を保証するためにバッファリングが必要になる場合があり、並列処理の利点が損なわれます。ストリームに出会い順があるが、ユーザーがその出会い順を特に気にしない場合、unordered()を使用してストリームを明示的に並べ替えると、一部のステートフルまたはターミナル操作の並列パフォーマンスが向上する可能性があります。ただし、上記の「ブロックの重みの合計」の例など、ほとんどのストリームパイプラインは、