2015-09-11 6 views
12

ich voraussichtlich in der Lage sein zu verwenden Stream-:: flatMap wie dieseWarum ist die Verwendung von Stream :: flatMap falsch?

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()); 

Aber ich bekomme die folgende Compiler-Fehler

Test.java:25: error: incompatible types: cannot infer type-variable(s) R listOfStrings.stream().flatMap(str -> duplicate(str)).collect(Collectors.toList());

(argument mismatch; bad return type in lambda expression List cannot be converted to Stream)
where R,T are type-variables: R extends Object declared in method flatMap(Function>) T extends Object declared in interface Stream

In scala kann ich tun, was ich Äquivalent

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

Warum ist dies keine gültige Verwendung von FlatMap in Java?

Antwort

19

Der Lambda-Ausdruck in flatMap braucht ein Stream zurückzukehren, wie es durch das Argument von flatMap gesehen werden kann, die von Function<? super T, ? extends Stream<? extends R>> Typ ist.

Der folgende Code kompilieren und ausführen fein:

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

, weil der Ausdruck Lambda str -> duplicate(str).stream() vom Typ Function<String, Stream<String>>.

6

Wenn Sie jedes Objekt mehrmals im Stream duplizieren möchten, müssen Sie dafür keinen zusätzlichen Speicher mit ArrayList verschwenden. Es gibt mehrere kürzere und schnellere Alternativen.

  • Neuen Strom Stream.generate verwenden, dann begrenzen:

    listOfStrings.stream() 
          .flatMap(str -> Stream.generate(() -> str).limit(2)) 
          .collect(Collectors.toList()); 
    
  • generieren Folge von Zahlen über IntStream.range und ordnet sie auf die gleiche Zeichenfolge:

    listOfStrings.stream() 
          .flatMap(str -> IntStream.range(0, 2).mapToObj(i -> str)) 
          .collect(Collectors.toList()); 
    
  • Verwenden guten alten Collections.nCopies:

    listOfStrings.stream() 
          .flatMap(str -> Collections.nCopies(2, str).stream()) 
          .collect(Collectors.toList()); 
    

Wenn Sie sicher sind, dass Sie immer genau zwei Mal dupliziert, dann ist es die kürzeste Alternative:

listOfStrings.stream() 
      .flatMap(str -> Stream.of(str, str)) 
      .collect(Collectors.toList()); 
Verwandte Themen