Was ist der Unterschied zwischen diesen beiden Methoden: Optional.flatMap()
und Optional.map()
?
Ein Beispiel wäre wünschenswert.
co-abhängig
Was ist der Unterschied zwischen diesen beiden Methoden: Optional.flatMap()
und Optional.map()
?
Ein Beispiel wäre wünschenswert.
Assyrien
Benutzen map
ob die Funktion das benötigte Objekt zurückgibt oder flatMap
wenn die Funktion eine zurückgibt Optional
. Zum Beispiel:
public static void main(String[] args) {
Optional<String> s = Optional.of("input");
System.out.println(s.map(Test::getOutput));
System.out.println(s.flatMap(Test::getOutputOpt));
}
static String getOutput(String input) {
return input == null ? null : "output for " + input;
}
static Optional<String> getOutputOpt(String input) {
return input == null ? Optional.empty() : Optional.of("output for " + input);
}
Beide print-Anweisungen geben dasselbe aus.
Frage: würde [flat]Map
Rufen Sie die Zuordnungsfunktion jemals mit an auf input == null
? Mein Verständnis ist das Optional
sortcuts, wenn es nicht vorhanden ist – die [JavaDoc ](docs.oracle.com/javase/8/docs/api/java/util/…) scheint dies zu untermauern – “Wenn ein Wert vorhanden ist, gelten …“.
– Boris die Spinne
19. Februar 2016 um 10:24 Uhr
@BoristheSpider Optional.of(null) != Optional.empty()
– Diego Martinoia
6. Oktober 2016 um 9:36 Uhr
@DiegoMartinoia Optional.of(null)
ist ein Exception
. Optional.ofNullable(null) == Optional.empty()
.
– Boris die Spinne
6. Oktober 2016 um 9:38 Uhr
@BoristheSpider ja, du hast recht. Ich habe versucht, auf Ihre Frage zu antworten, aber ich glaube, ich habe es noch unklarer gemacht: konzeptionell sollte Optional.ofNullable(null) NICHT leer sein, aber in der Praxis wird es als so angesehen, und daher werden Map/Flatmap nicht ausgeführt.
– Diego Martinoia
6. Oktober 2016 um 9:44 Uhr
Ich denke, die Eingabe sollte weder in getOutputOpt noch in getOutput null sein
– DanyalBurke
14. März 2017 um 11:47 Uhr
Diego Martinoia
Beide übernehmen eine Funktion vom Typ des Optionalen zu etwas.
map()
wendet die Funktion “wie es ist” Optional haben Sie:
if (optional.isEmpty()) return Optional.empty();
else return Optional.of(f(optional.get()));
Was passiert, wenn Ihre Funktion eine Funktion von ist T -> Optional<U>
?
Ihr Ergebnis ist jetzt ein Optional<Optional<U>>
!
Das ist, was flatMap()
geht es um: wenn Ihre Funktion bereits eine zurückgibt Optional
, flatMap()
ist ein bisschen schlauer und wickelt es nicht doppelt ein und kehrt zurück Optional<U>
.
Es ist die Zusammensetzung von zwei funktionalen Redewendungen: map
und flatten
.
Okay. Du Sie müssen ‘flatMap’ nur verwenden, wenn Sie mit verschachtelten Optionals konfrontiert sind. Hier ist das Beispiel.
public class Person {
private Optional<Car> optionalCar;
public Optional<Car> getOptionalCar() {
return optionalCar;
}
}
public class Car {
private Optional<Insurance> optionalInsurance;
public Optional<Insurance> getOptionalInsurance() {
return optionalInsurance;
}
}
public class Insurance {
private String name;
public String getName() {
return name;
}
}
public class Test {
// map cannot deal with nested Optionals
public Optional<String> getCarInsuranceName(Person person) {
return person.getOptionalCar()
.map(Car::getOptionalInsurance) // ① leads to a Optional<Optional<Insurance>
.map(Insurance::getName); // ②
}
}
Wie Stream gibt Optional#map einen Wert zurück, der von einem Optional umschlossen ist. Deshalb bekommen wir ein verschachteltes Optional — Optional<Optional<Insurance>
. Und bei ② wollen wir es als Versicherungsinstanz abbilden, so ist die Tragödie passiert. Die Wurzel sind verschachtelte Optionals. Wenn wir den Kernwert unabhängig von den Hüllen erhalten können, werden wir es schaffen. Das macht flatMap.
public Optional<String> getCarInsuranceName(Person person) {
return person.getOptionalCar()
.flatMap(Car::getOptionalInsurance)
.map(Insurance::getName);
}
Am Ende habe ich das dringend empfohlen Java 8 in Aktion an Sie, wenn Sie Java8 systematisch lernen möchten.
SandeepGodara
Hinweis:- Unten ist die Abbildung der Map- und Flatmap-Funktion, ansonsten ist Optional in erster Linie nur für die Verwendung als Rückgabetyp konzipiert.
Wie Sie vielleicht bereits wissen, ist Optional eine Art Container, der ein einzelnes Objekt enthalten kann oder nicht, sodass es überall dort verwendet werden kann, wo Sie einen Nullwert erwarten (Sie werden NPE möglicherweise nie sehen, wenn Sie Optional richtig verwenden). Wenn Sie beispielsweise eine Methode haben, die ein Personenobjekt erwartet, das nullable sein kann, möchten Sie die Methode vielleicht so schreiben:
void doSome(Optional<Person> person){
/*and here you want to retrieve some property phone out of person
you may write something like this:
*/
Optional<String> phone = person.map((p)->p.getPhone());
phone.ifPresent((ph)->dial(ph));
}
class Person{
private String phone;
//setter, getters
}
Hier haben Sie einen String-Typ zurückgegeben, der automatisch in einen optionalen Typ eingeschlossen wird.
Wenn die Personenklasse so aussah, ist Telefon auch optional
class Person{
private Optional<String> phone;
//setter,getter
}
In diesem Fall umschließt der Aufruf der map-Funktion den zurückgegebenen Wert in Optional und ergibt so etwas wie:
Optional<Optional<String>>
//And you may want Optional<String> instead, here comes flatMap
void doSome(Optional<Person> person){
Optional<String> phone = person.flatMap((p)->p.getPhone());
phone.ifPresent((ph)->dial(ph));
}
PS; Rufen Sie niemals die get-Methode (falls erforderlich) für ein Optional auf, ohne es mit isPresent() zu überprüfen, es sei denn, Sie können nicht ohne NullPointerExceptions leben.
Robert Niestroj
Was mir geholfen hat, war ein Blick in den Quellcode der beiden Funktionen.
Karte – schließt das Ergebnis in ein Optional ein.
public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else {
return Optional.ofNullable(mapper.apply(value)); //<--- wraps in an optional
}
}
flachKarte – gibt das ‘rohe’ Objekt zurück
public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else {
return Objects.requireNonNull(mapper.apply(value)); //<--- returns 'raw' object
}
}
Was meinst du mit flatMap
“gibt das ‘rohe’ Objekt zurück”? flatMap
gibt auch das zugeordnete Objekt “verpackt” in an zurück Optional
. Der Unterschied besteht darin, dass im Fall von flatMap
umschließt die Mapper-Funktion das zugeordnete Objekt in der Optional
während map
selbst hüllt das Objekt ein Optional
.
– Derek Mahar
9. Oktober 2019 um 8:46 Uhr
@DerekMahar hat meinen gelöscht, keine Notwendigkeit, ihn erneut zu posten, da Sie Ihren Kommentar richtig bearbeitet haben.
– maxxime
10. Oktober 2019 um 12:04 Uhr
Optional.map()
:Nimmt jedes Element und wenn der Wert existiert, wird er an die Funktion übergeben:
Optional<T> optionalValue = ...;
Optional<Boolean> added = optionalValue.map(results::add);
Jetzt hinzugefügt hat einen von drei Werten: true
oder false
eingewickelt in ein Optional Wenn optionalValue
anwesend war, oder ein leer Optional ansonsten.
Wenn Sie das Ergebnis nicht verarbeiten müssen, können Sie es einfach verwenden ifPresent()
es hat keinen Rückgabewert:
optionalValue.ifPresent(results::add);
Optional.flatMap()
:Funktioniert ähnlich wie die gleiche Methode von Streams. Flacht den Stream von Streams ab. Mit dem Unterschied, dass, wenn der Wert präsentiert wird, er auf Funktion angewendet wird. Andernfalls wird eine leere Option zurückgegeben.
Sie können es verwenden, um Funktionsaufrufe mit optionalen Werten zu erstellen.
Angenommen, wir haben Methoden:
public static Optional<Double> inverse(Double x) {
return x == 0 ? Optional.empty() : Optional.of(1 / x);
}
public static Optional<Double> squareRoot(Double x) {
return x < 0 ? Optional.empty() : Optional.of(Math.sqrt(x));
}
Dann können Sie die Quadratwurzel der Inversen berechnen, wie:
Optional<Double> result = inverse(-4.0).flatMap(MyMath::squareRoot);
oder, wenn Sie es vorziehen:
Optional<Double> result = Optional.of(-4.0).flatMap(MyMath::inverse).flatMap(MyMath::squareRoot);
Wenn entweder die inverse()
oder der squareRoot()
kehrt zurück Optional.empty()
das Ergebnis ist leer.
Was meinst du mit flatMap
“gibt das ‘rohe’ Objekt zurück”? flatMap
gibt auch das zugeordnete Objekt “verpackt” in an zurück Optional
. Der Unterschied besteht darin, dass im Fall von flatMap
umschließt die Mapper-Funktion das zugeordnete Objekt in der Optional
während map
selbst hüllt das Objekt ein Optional
.
– Derek Mahar
9. Oktober 2019 um 8:46 Uhr
@DerekMahar hat meinen gelöscht, keine Notwendigkeit, ihn erneut zu posten, da Sie Ihren Kommentar richtig bearbeitet haben.
– maxxime
10. Oktober 2019 um 12:04 Uhr
Matthias Stephan
Sie können sich auf den folgenden Link beziehen, um es im Detail zu verstehen (beste Erklärung, die ich finden konnte):
https://www.programmergirl.com/java-8-map-flatmap-difference/
Sowohl map als auch flatMap – Accept Function. Der Rückgabetyp von map() ist ein einzelner Wert, während flatMap einen Strom von Werten zurückgibt
<R> Stream<R> map(Function<? super T, ? extends R> mapper)
<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper)
In Ihren Methodensignaturen sind beide Rückgabetypen Streams? Ich dachte, dass flatMap
würde einfach verschachtelte optional auspacken? Können Sie näher erläutern, wie sich dies auf Streams bezieht?
– Yu Chen
15. Januar um 21:37 Uhr
Siehe stackoverflow.com/questions/26684562/…
– Alexis C.
16. Juni 2015 um 10:14 Uhr
@AlexisC. Ihr Link bezieht sich auf die Karte und die FlatMap von Stream, nicht auf Optional.
– Eran
16. Juni 2015 um 10:16 Uhr
@Eran Das spielt keine Rolle, wenn Sie verstehen, wie map/flatMap funktioniert, ob es sich um einen Stream handelt oder nicht, ist es dasselbe für ein Optional. Wenn der Op verstanden hat, wie es für einen Stream funktioniert, sollte er diese Frage nicht stellen. Das Konzept ist das gleiche.
– Alexis C.
16. Juni 2015 um 10:18 Uhr
@AlexisC. Nicht wirklich. Die flatMap von Optional hat wenig mit der flatMap von Stream gemeinsam.
– Eran
16. Juni 2015 um 10:22 Uhr
@Eran Ich spreche über die konzeptionell Unterschied zwischen einer Karte und einer FlatMap mache ich keine Eins-zu-Eins-Korrespondenz zwischen
Stream#flatMap
undOptional#flatMap
.– Alexis C.
16. Juni 2015 um 10:28 Uhr