背景
Javaでパラレルストリームを使用すると、forEachでは順番がランダムになる。
List<String> list = List.of("A", "B", "C"); list.parallelStream().forEach(System.out::println); // B C A など
Collectors.toList()で集約したリストは元の配列の順番に並びます。
List<String> list = List.of("A", "B", "C"); List<String> parallelList = list.parallelStream().collect(Collectors.toList()); parallelList.forEach(System.out::println); // A B C
Collectors.toList()を使用した場合、元の順番どおりに並ぶことは保証されているのか
結論
順番は保証されている
途中、sortedなどを挟んでいる場合はそちらの順番で並ぶ。
Javadocを確認する
Collectors.toList()のJavadocを確認すると、以下のように書いてあります。
すべての入力要素を検出順にList内に集めるCollector
検出順とは何でしょうか。 In what order do the elements of a stream become available? | Maurice Naftalin's Lambda FAQ の記事が分かりやすかったので引用します。
The source has an encounter order : this is the order in which the source itself makes its elements available. For example, the encounter order for an array is defined by the ordering of its elements; for an ordered collection like a List or a NavigableMap, by its iteration order; for a generator function by the function itself, and so on.
訳すと、
入力は検出順序を持つ: 検出順序とは、そのオブジェクトが持っているメンバーを取り出す際の順序のことである。例えば、配列の検出順序はその並びそのものであるし、ListやNavigableMapなどのコレクションの検出順序は、イテレータで取り出される順序のことであるし、ジェネレータであれば、それが生成する順のことである。 ればその順番が保存されるということです。
つまり、Collectors.toList()は入力のListの順番通りに並ぶことが分かります。