このようにStream :: flatMapを使用できると期待していました
public static List<String> duplicate(String s) {
List<String> l = new ArrayList<String>();
l.add(s);
l.add(s);
return l;
}
listOfStrings.stream().flatMap(str -> duplicate(str)).collect(Collectors.toList());
しかし、次のコンパイラエラーが発生します
Test.Java:25:エラー:互換性のないタイプ:タイプ変数を推測できませんR listOfStrings.stream()。flatMap(str-> duplicate(str))。collect(Collectors.toList());
(引数の不一致。ラムダ式リストの戻り値の型が正しくないため、ストリームに変換できません)
ここで、R、Tは型変数です。RはメソッドflatMap(Function>)で宣言されたオブジェクトを拡張しますTはインターフェイスStreamで宣言されたオブジェクトを拡張します
In scala私は同等だと信じていることをすることができます
scala> List(1,2,3).flatMap(duplicate(_))
res0: List[Int] = List(1, 1, 2, 2, 3, 3)
これがJavaでのflatMapの有効な使用法ではないのはなぜですか?
flatMap
のラムダ式はStream
を返す必要があります。これは、Function<? super T, ? extends Stream<? extends R>>
型のflatMap
の引数からわかります。
次のコードはコンパイルされ、正常に実行されます。
listOfStrings.stream()
.flatMap(str -> duplicate(str).stream()) // note the .stream() here
.collect(Collectors.toList());
ラムダ式str -> duplicate(str).stream()
のタイプはFunction<String, Stream<String>>
であるためです。
ストリーム内の各オブジェクトを複数回複製する場合は、ArrayList
を追加してメモリを浪費する必要はありません。より短く、より速い選択肢がいくつかあります。
Stream.generate
を使用して新しいストリームを生成し、それを制限します。
listOfStrings.stream()
.flatMap(str -> Stream.generate(() -> str).limit(2))
.collect(Collectors.toList());
IntStream.range
を介して一連の数値を生成し、それらを同じ文字列にマップします。
listOfStrings.stream()
.flatMap(str -> IntStream.range(0, 2).mapToObj(i -> str))
.collect(Collectors.toList());
古き良きCollections.nCopies
を使用する:
listOfStrings.stream()
.flatMap(str -> Collections.nCopies(2, str).stream())
.collect(Collectors.toList());
常に正確に2回複製することが確実な場合は、最短の方法があります。
listOfStrings.stream()
.flatMap(str -> Stream.of(str, str))
.collect(Collectors.toList());