###実現したいこと
Javaの学習中に疑問に思ったことがあります。
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6); list.parallelStream().filter(v -> v > 3).forEach(System.out::println);
のようにforEachを使うと順序が無視されます。
StreamAPIをつかって(for文を使わず)リストの要素に順序良くアクセスすることはできないのでしょうか。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

回答3件
0
ベストアンサー
forEachを使うと順序が無視されます。
Stream APIの仕様通りの挙動です。処理順序が重要な場合にはforEach
メソッドを使ってはいけません。
この操作の動作は明らかに非決定論的です。並列ストリーム・パイプラインの場合、この操作は、ストリームの検出順序を考慮することを保証しません。保証すると並列性のメリットが犠牲になるからです。与えられた任意の要素に対し、ライブラリが選択した任意のタイミングで任意のスレッド内でアクションが実行される可能性があります。アクションが共有状態にアクセスする場合、必要な同期を提供する責任はアクションにあります。
データの順序を維持した終端処理を行いたければ、forEachOrdered
メソッドを使ってください。順序性の維持は、(逐次ストリームは当然ながら)並列ストリームであっても正しく維持されます。
java
1list.parallelStream().filter(v -> v > 3).forEachOrdered(System.out::println);
この場合、ストリームパイプラインの中間操作filter(v -> v > 3)
は並列に処理されますが、終端処理forEachOrdered(System.out::println)
は元データの順序性を維持して逐次実行されます。
投稿2016/05/27 12:33
編集2016/05/27 12:36総合スコア6191
0
順序を保証するための対策は、yohhoyさんの回答が適切だと思います。
そちらを参照してください。
Collection#parallelStream
を使っているからです。
parallelStream
では 並列ストリーム が作られるので、複数スレッドに分割されて実行され、終わった順に結果が出力されます。
Collection#stream
の方を使えば、
つまりlist.stream()
とすれば、並列でないストリームが作られるので、順番通りに結果が出力されます。
参考リンク:
Collection.parallelStream
- Java SE 8 API ドキュメント
https://docs.oracle.com/javase/jp/8/docs/api/java/util/Collection.html#parallelStream--
投稿2016/05/27 11:04
編集2016/05/27 14:34総合スコア9396
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/05/27 13:11

あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/05/30 07:16