Het verschil tussen map () en flatMap ()

1. Overzicht

kaart() en flatMap () API's komen voort uit functionele talen. In Java 8 kun je ze vinden in Optioneel, Stream en in CompletableFuture (hoewel onder iets andere naam).

Streams vertegenwoordigen een reeks objecten, terwijl optionals klassen zijn die een waarde vertegenwoordigen die aanwezig of afwezig kan zijn. Naast andere geaggregeerde operaties hebben we de kaart() en flatMap () methoden.

Ondanks het feit dat beide dezelfde retourtypen hebben, ze zijn heel verschillend. Laten we deze verschillen uitleggen door enkele voorbeelden van streams en opties te analyseren.

2. Map en Flatmap in Optionals

De kaart() methode werkt goed met Optioneel - als de functie het exacte type retourneert dat we nodig hebben:

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

In meer complexe gevallen kunnen we echter een functie krijgen die een retourneert Optioneel te. Gebruik in dergelijke gevallen kaart() zou leiden tot een geneste structuur, zoals de kaart() implementatie doet intern een extra verpakking.

Laten we nog een voorbeeld bekijken om een ​​beter begrip van deze situatie te krijgen:

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

Zoals we kunnen zien, eindigen we met de geneste structuur Optioneel. Hoewel het werkt, is het behoorlijk omslachtig in het gebruik en biedt het geen extra nulveiligheid, dus het is beter om een ​​platte structuur te houden.

Dat is precies wat flatMap () helpt ons bij:

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

3. Kaart en Flatmap in Streams

Beide methoden werken op dezelfde manier voor Optioneel.

De kaart() methode wikkelt de onderliggende reeks in een Stroom bijvoorbeeld, terwijl de flatMap () methode maakt het vermijden van geneste Stroom structuur.

In het volgende voorbeeld kaart() produceert een Stroom bestaande uit de resultaten van het toepassen van de toUpperCase () methode aan de elementen van de invoer Stroom:

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

kaart() werkt redelijk goed in zo'n eenvoudig geval, maar wat als we iets complexers hebben, zoals een lijst met lijsten als invoer.

Laten we eens kijken hoe het werkt:

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

Dit fragment drukt een lijst met lijsten af [[a], [b]].

Laten we nu een flatMap ():

System.out.println (lijst .stream () .flatMap (Collectie :: stream) .collect (Collectors.toList ()));

Het resultaat van een dergelijk fragment wordt afgevlakt tot [a, b].

Thij flatMap () methode maakt eerst de invoer af Stroom van Streams naar een Stroom van Snaren (zie het artikel voor meer informatie over afvlakken). Daarna werkt het op dezelfde manier als het kaart() methode.

4. Conclusie

Java 8 geeft ons de mogelijkheid om de kaart() en flatMap () methoden die oorspronkelijk in functionele talen werden gebruikt.

We kunnen ze inschakelen Streams en Optionals. Deze methoden helpen ons om in kaart gebrachte objecten te krijgen door de meegeleverde mapping-functie toe te passen.

Zoals altijd kun je de voorbeelden in dit artikel bekijken op GitHub.