21

このように 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());

(引数の不一致。ラムダ式 List の不正な戻り値の型は Stream に変換できません)
ここで、R、T は型変数です: R は、メソッド flatMap(Function>) で宣言されたオブジェクトを拡張します。 T は、インターフェイス Stream で宣言されたオブジェクトを拡張します。

scalaでは、私が同等だと信じていることを行うことができます

scala> List(1,2,3).flatMap(duplicate(_))
res0: List[Int] = List(1, 1, 2, 2, 3, 3)

なぜこれが Java での flatMap の有効な使用法ではないのですか?

4

2 に答える 2

28

のラムダ式は、型がの引数からわかるように、flatMapを返す必要があります。StreamflatMapFunction<? super T, ? extends Stream<? extends R>>

次のコードは正常にコンパイルおよび実行されます。

listOfStrings.stream()
             .flatMap(str -> duplicate(str).stream()) // note the .stream() here
             .collect(Collectors.toList());

ラムダ式str -> duplicate(str).stream()は型であるためFunction<String, Stream<String>>です。

于 2015-09-11T08:13:54.917 に答える
8

ストリーム内の各オブジェクトを数回複製したい場合、追加でこれにメモリを浪費する必要はありません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());
于 2015-09-11T09:46:27.890 に答える