teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

1

append

2016/05/27 12:36

投稿

yohhoy
yohhoy

スコア6191

answer CHANGED
@@ -1,11 +1,13 @@
1
1
  > forEachを使うと順序が無視されます。
2
2
 
3
- Stream APIの仕様通りの挙動です。処理順序が重要な場合には`forEach`メソッドを**使ってはいけません**。
3
+ Stream APIの仕様通りの挙動です。処理順序が重要な場合には[`forEach`メソッド](https://docs.oracle.com/javase/jp/8/docs/api/java/util/stream/Stream.html#forEach-java.util.function.Consumer-)を**使ってはいけません**。
4
+ > この操作の動作は明らかに非決定論的です。並列ストリーム・パイプラインの場合、この操作は、ストリームの検出順序を考慮することを保証しません。保証すると並列性のメリットが犠牲になるからです。与えられた任意の要素に対し、ライブラリが選択した任意のタイミングで任意のスレッド内でアクションが実行される可能性があります。アクションが共有状態にアクセスする場合、必要な同期を提供する責任はアクションにあります。
4
5
 
6
+ ----
5
7
  データの順序を維持した終端処理を行いたければ、`forEachOrdered`メソッドを使ってください。順序性の維持は、(逐次ストリームは当然ながら)並列ストリームであっても正しく維持されます。
6
8
 
7
9
  ```java
8
10
  list.parallelStream().filter(v -> v > 3).forEachOrdered(System.out::println);
9
11
  ```
10
12
 
11
- この場合、ストリームパイプラインの中間操作`filter(v -> v > 3)`は並列に処理されますが、終端処理`forEachOrdered(System.out::println)`は元データの順序性を維持して実行されます。
13
+ この場合、ストリームパイプラインの中間操作`filter(v -> v > 3)`は並列に処理されますが、終端処理`forEachOrdered(System.out::println)`は元データの順序性を維持して逐次実行されます。