Der Unterschied zwischen map () und flatMap ()

1. Übersicht

Die APIs map () und flatMap () stammen aus funktionalen Sprachen. In Java 8 finden Sie sie in Optional, Stream und CompletableFuture (allerdings unter etwas anderem Namen).

Streams stellen eine Folge von Objekten dar, während Optionals Klassen sind, die einen Wert darstellen, der vorhanden sein oder fehlen kann. Unter anderen aggregierten Operationen haben wir die Methoden map () und flatMap () .

Trotz der Tatsache, dass beide die gleichen Rückgabetypen haben , sind sie sehr unterschiedlich. Lassen Sie uns diese Unterschiede anhand einiger Beispiele für Streams und Optionen erklären.

2. Karte und Flatmap in Optionals

Die map () -Methode funktioniert gut mit Optional - wenn die Funktion den genauen Typ zurückgibt, den wir benötigen:

Optional s = Optional.of("test"); assertEquals(Optional.of("TEST"), s.map(String::toUpperCase));

In komplexeren Fällen erhalten wir jedoch möglicherweise eine Funktion, die auch eine Option zurückgibt . In solchen Fällen würde die Verwendung von map () zu einer verschachtelten Struktur führen, da die Implementierung von map () intern einen zusätzlichen Umbruch durchführt.

Sehen wir uns ein weiteres Beispiel an, um diese Situation besser zu verstehen:

assertEquals(Optional.of(Optional.of("STRING")), Optional .of("string") .map(s -> Optional.of("STRING")));

Wie wir sehen können, erhalten wir die verschachtelte Struktur Optional . Obwohl es funktioniert, ist es ziemlich umständlich zu bedienen und bietet keine zusätzliche Nullsicherheit, daher ist es besser, eine flache Struktur beizubehalten.

Genau das hilft uns flatMap () :

assertEquals(Optional.of("STRING"), Optional .of("string") .flatMap(s -> Optional.of("STRING")));

3. Karte und Flatmap in Streams

Beide Methoden funktionieren für Optional ähnlich .

Die map () -Methode umschließt die zugrunde liegende Sequenz in einer Stream- Instanz, während die flatMap () -Methode das Vermeiden verschachtelter Streams ermöglicht Struktur.

Im folgenden Beispiel erzeugt map () einen Stream , der aus den Ergebnissen der Anwendung der toUpperCase () -Methode auf die Elemente des Eingabestreams besteht :

List myList = Stream.of("a", "b") .map(String::toUpperCase) .collect(Collectors.toList()); assertEquals(asList("A", "B"), myList);

map () funktioniert in einem so einfachen Fall ziemlich gut, aber was ist, wenn wir etwas Komplexeres haben, wie eine Liste von Listen als Eingabe.

Mal sehen, wie es funktioniert:

List
    
      list = Arrays.asList( Arrays.asList("a"), Arrays.asList("b")); System.out.println(list);
    

Dieses Snippet druckt eine Liste von Listen [[a], [b]].

Verwenden wir jetzt eine flatMap () :

System.out.println(list .stream() .flatMap(Collection::stream) .collect(Collectors.toList()));

Das Ergebnis eines solchen Snippets wird auf [a, b] abgeflacht .

T er flatMap () Methode flacht zuerst den Eingangsstrom von Streams zu einem Strom von Strings (für mehr über Abflachung, um den Artikel zu sehen). Danach funktioniert es ähnlich wie bei der map () -Methode.

4. Fazit

Java 8 bietet uns die Möglichkeit, die Methoden map () und flatMap () zu verwenden, die ursprünglich in funktionalen Sprachen verwendet wurden.

Wir können sie auf Streams und Optionals aufrufen . Diese Methoden helfen uns, zugeordnete Objekte zu erhalten, indem wir die bereitgestellte Zuordnungsfunktion anwenden.

Wie immer können Sie die Beispiele in diesem Artikel auf GitHub nachlesen.