List
Java 8 を使用し、提案された (そして受け入れられた) ソリューションのように、自分でインスタンスをインスタンス化したくない場合
someMap.values().forEach(someList::addAll);
次のステートメントを使用してストリーミングすることで、すべてを実行できます。
List<String> someList = map.values().stream().flatMap(c -> c.stream()).collect(Collectors.toList());
ちなみに興味深いことに、Java 8 では承認されたバージョンが実際に最速のようです。とほぼ同じタイミングです。
for (List<String> item : someMap.values()) ...
純粋なストリーミング ソリューションよりもはるかに高速です。これが私の小さなテストコードです。ベンチマークの欠陥に関する議論を避けるため、ベンチマークとは明示的に名前を付けません。;) できれば完全にコンパイルされたバージョンを取得するために、すべてのテストを 2 回行います。
Map<String, List<String>> map = new HashMap<>();
long millis;
map.put("test", Arrays.asList("1", "2", "3", "4"));
map.put("test2", Arrays.asList("10", "20", "30", "40"));
map.put("test3", Arrays.asList("100", "200", "300", "400"));
int maxcounter = 1000000;
System.out.println("1 stream flatmap");
millis = System.currentTimeMillis();
for (int i = 0; i < maxcounter; i++) {
List<String> someList = map.values().stream().flatMap(c -> c.stream()).collect(Collectors.toList());
}
System.out.println(System.currentTimeMillis() - millis);
System.out.println("1 parallel stream flatmap");
millis = System.currentTimeMillis();
for (int i = 0; i < maxcounter; i++) {
List<String> someList = map.values().parallelStream().flatMap(c -> c.stream()).collect(Collectors.toList());
}
System.out.println(System.currentTimeMillis() - millis);
System.out.println("1 foreach");
millis = System.currentTimeMillis();
for (int i = 0; i < maxcounter; i++) {
List<String> mylist = new ArrayList<String>();
map.values().forEach(mylist::addAll);
}
System.out.println(System.currentTimeMillis() - millis);
System.out.println("1 for");
millis = System.currentTimeMillis();
for (int i = 0; i < maxcounter; i++) {
List<String> mylist = new ArrayList<String>();
for (List<String> item : map.values()) {
mylist.addAll(item);
}
}
System.out.println(System.currentTimeMillis() - millis);
System.out.println("2 stream flatmap");
millis = System.currentTimeMillis();
for (int i = 0; i < maxcounter; i++) {
List<String> someList = map.values().stream().flatMap(c -> c.stream()).collect(Collectors.toList());
}
System.out.println(System.currentTimeMillis() - millis);
System.out.println("2 parallel stream flatmap");
millis = System.currentTimeMillis();
for (int i = 0; i < maxcounter; i++) {
List<String> someList = map.values().parallelStream().flatMap(c -> c.stream()).collect(Collectors.toList());
}
System.out.println(System.currentTimeMillis() - millis);
System.out.println("2 foreach");
millis = System.currentTimeMillis();
for (int i = 0; i < maxcounter; i++) {
List<String> mylist = new ArrayList<String>();
map.values().forEach(mylist::addAll);
}
System.out.println(System.currentTimeMillis() - millis);
System.out.println("2 for");
millis = System.currentTimeMillis();
for (int i = 0; i < maxcounter; i++) {
List<String> mylist = new ArrayList<String>();
for (List<String> item : map.values()) {
mylist.addAll(item);
}
}
System.out.println(System.currentTimeMillis() - millis);
結果は次のとおりです。
1 stream flatmap
468
1 parallel stream flatmap
1529
1 foreach
140
1 for
172
2 stream flatmap
296
2 parallel stream flatmap
1482
2 foreach
156
2 for
141
2016-05-24 を編集 (2 年後):
同じマシンで実際の Java 8 バージョン (U92) を使用して同じテストを実行します。
1 stream flatmap
313
1 parallel stream flatmap
3257
1 foreach
109
1 for
141
2 stream flatmap
219
2 parallel stream flatmap
3830
2 foreach
125
2 for
140
ストリームの順次処理の高速化と、並列ストリームのさらに大きなオーバーヘッドがあるようです。
2018-10-18 を編集 (4 年後):
同じマシンで Java 10 バージョン (10.0.2) を使用する場合:
1 stream flatmap
393
1 parallel stream flatmap
3683
1 foreach
157
1 for
175
2 stream flatmap
243
2 parallel stream flatmap
5945
2 foreach
128
2 for
187
並列ストリーミングのオーバーヘッドの方が大きいようです。
2020-05-22 を編集 (6 年後):
別のマシンで Java 14 バージョン (14.0.0.36) を使用する場合:
1 stream flatmap
299
1 parallel stream flatmap
3209
1 foreach
202
1 for
170
2 stream flatmap
178
2 parallel stream flatmap
3270
2 foreach
138
2 for
167
これは別のマシンで行われたことに注意してください(ただし、同等だと思います)。並列ストリーミングのオーバーヘッドは、以前よりかなり小さくなっているようです。