yucatio@システムエンジニア

趣味で作ったものいろいろ

JavaのパラレルストリームでCollectors.toList()は順番に並ぶか

背景

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

Collectors (Java SE 11 & JDK 11 )

検出順とは何でしょうか。 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の順番通りに並ぶことが分かります。

参考