In Java 8, qual è la differenza tra i metodi Stream.map()
e Stream.flatMap()
?
Antworten
Zu viele Anzeigen?Definitionen dieser Stream-API-Methoden:
map(Funktion mapper) ist eine Zwischenoperation, die einen Stream zurückgibt, der aus den Ergebnissen besteht, die durch Anwendung der gegebenen Funktion auf die Elemente dieses Streams erhalten werden.
flatMap(Funktion mapper) ist eine Zwischenoperation, die einen Stream zurückgibt, der aus den Ergebnissen besteht, die durch Ersetzen jedes Elements dieses Streams durch den Inhalt eines von der bereitgestellten Zuordnungsfunktion auf jedes Element angewendeten gemappten Streams erhalten werden. Kurz gesagt wird es verwendet, um einen Stream von Streams in eine Liste von Werten umzuwandeln.
Schauen wir uns ein Beispiel an:
List myList = Stream.of("Apfel", "Orange")
.map(String::toUpperCase)
.collect(Collectors.toList());
System.out.println(myList);
Es wird gedruckt: [APFEL, ORANGE]
Können wir einfach map()
zu flatMap()
ändern?
List myListFlat = Stream.of("Apfel", "Orange")
.flatMap(String::toUpperCase)
.collect(Collectors.toList());
System.out.println(myListFlat);
Nein, jetzt sehen wir einen Fehler:
java: inkompatible Typen: kann Typ-Variable(s) R nicht ableiten
(Argumentfehlanpassung; falscher Rückgabetyp bei Methodenreferenz
java.lang.String kann nicht in java.util.stream.Stream konvertiert werden)
Warum ist das so? Schauen wir uns die Methodensignaturen an:
Stream map(Function mapper);
Stream flatMap(Function> mapper);
Der Grund, warum der Code nicht funktioniert, ist, dass die Methode flatMap()
eine Funktion erwartet, die einen Stream zurückgibt. Im zweiten Beispiel übergebe ich jedoch eine Methodenreferenz an String.toUpperCase()
, die einen String zurückgibt. Daher versuche ich, flatMap()
auf einem Stream von Zeichen anzuwenden, anstatt auf einem Stream von Strings.
Also haben wir jetzt eine Vorstellung davon, wofür flatMap()
verwendet wird. Lassen Sie uns eine Liste von Listen erstellen:
List> list = Arrays.asList(
Arrays.asList("Apfel"),
Arrays.asList("Orange"));
System.out.println(list);
und es druckt: [[Apfel], [Orange]]
. Wenn wir es flach haben wollen, verwenden wir flatMap()
:
List flattedList = list
.stream()
.flatMap(Collection::stream)
.collect(Collectors.toList());
System.out.println(flattedList);
und jetzt druckt es: [Apfel, Orange]
Quellen: https://www.geeksforgeeks.org/stream-flatmap-java-examples/
flatMap()
macht auch teilweise von der verzögerten Auswertung von Streams Gebrauch. Es liest den ersten Stream und geht erst zum nächsten Stream über, wenn erforderlich. Das Verhalten wird hier ausführlich erklärt: Ist flatMap garantiert faul zu sein?
Streamoperationen flatMap
und map
akzeptieren eine Funktion als Eingabe.
flatMap
erwartet, dass die Funktion für jedes Element des Streams einen neuen Stream zurückgibt und einen Stream zurückgibt, der alle Elemente der Streams kombiniert, die von der Funktion für jedes Element zurückgegeben werden. Mit anderen Worten, mit flatMap
werden für jedes Element aus der Quelle mehrere Elemente durch die Funktion erstellt. http://www.zoftino.com/java-stream-examples#flatmap-operation
map
erwartet, dass die Funktion einen transformierten Wert zurückgibt und einen neuen Stream zurückgibt, der die transformierten Elemente enthält. Mit anderen Worten, mit map
wird für jedes Element aus der Quelle ein transformiertes Element durch die Funktion erstellt. http://www.zoftino.com/java-stream-examples#map-operation
Dies ist sehr verwirrend für Anfänger. Der grundlegende Unterschied besteht darin, dass map
für jedes Element in der Liste ein Element ausgibt und flatMap
im Grunde eine map
+ flatten
Operation ist. Um es klarer zu machen, verwenden Sie flatMap, wenn Sie mehr als einen Wert benötigen, z.B. wenn Sie erwarten, dass eine Schleife Arrays zurückgibt, wird flatMap in diesem Fall wirklich hilfreich sein.
Ich habe einen Blog darüber geschrieben, den Sie hier überprüfen können hier.