@AlexisC. Ihr Link bezieht sich auf die Karte und die flatMap von Stream, nicht auf Optional.
Eran
1
@Eran Das spielt keine Rolle. Wenn Sie verstehen, wie map / flatMap funktioniert, ob es sich um einen Stream handelt oder nicht, gilt dies auch für einen optionalen Stream. 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.
2
@AlexisC. Nicht wirklich. Die flatMap von Optional hat wenig mit der flatMap von Stream zu tun.
Eran
1
@Eran Ich spreche über den konzeptionellen Unterschied zwischen einer Karte und einer flatMap. Ich mache keine Eins-zu-Eins-Entsprechung zwischen Stream#flatMapund Optional#flatMap.
Alexis C.
Antworten:
165
Verwenden Sie mapdiese Option, wenn die Funktion das benötigte Objekt zurückgibt oder flatMapwenn die Funktion ein zurückgibt Optional. Beispielsweise:
publicstaticvoid main(String[] args){Optional<String> s =Optional.of("input");System.out.println(s.map(Test::getOutput));System.out.println(s.flatMap(Test::getOutputOpt));}staticString getOutput(String input){return input ==null?null:"output for "+ input;}staticOptional<String> getOutputOpt(String input){return input ==null?Optional.empty():Optional.of("output for "+ input);}
Frage: Würde [flat]Mapjemals die Mapping-Funktion mit einem aufrufen input == null? Ich verstehe, dass OptionalSortcuts, wenn sie nicht vorhanden sind - das [JavaDoc] ( docs.oracle.com/javase/8/docs/api/java/util/… ) scheint dies zu unterstützen - " Wenn ein Wert vorhanden ist, wenden Sie an. . ".
@DiegoMartinoia Optional.of(null)ist ein Exception. Optional.ofNullable(null) == Optional.empty().
Boris die Spinne
1
@ BoristheSpider ja, du hast recht. Ich habe versucht, auf Ihre Frage zu antworten, aber ich denke, ich habe sie noch unklarer gemacht: Konzeptionell sollte Optional.ofNullable (null) NICHT leer sein, aber in der Praxis wird dies als solche angesehen, und Map / Flatmap werden daher nicht ausgeführt.
Diego Martinoia
1
Ich denke, Eingabe sollte weder in getOutputOpt noch in getOutput
DanyalBurke
55
Beide übernehmen eine Funktion vom Typ des Optionalen bis zu etwas.
map()wendet die Funktion " wie sie ist " auf die Option an, die Sie haben:
Was passiert, wenn Ihre Funktion eine Funktion von ist T -> Optional<U>?
Ihr Ergebnis ist jetzt ein Optional<Optional<U>>!
Darum geht flatMap()es: Wenn Ihre Funktion bereits eine zurückgibt Optional, flatMap()ist sie etwas intelligenter und umschließt sie nicht doppelt, sondern kehrt zurück Optional<U>.
Es ist die Zusammensetzung zweier funktionaler Redewendungen: mapund flatten.
Hinweis: - Nachfolgend finden Sie eine Abbildung der Karten- und Flatmap-Funktion. Andernfalls ist Optional in erster Linie für die Verwendung als Rückgabetyp vorgesehen.
Wie Sie vielleicht bereits wissen, ist Optional eine Art Container, der ein einzelnes Objekt enthalten kann oder nicht. Daher kann es überall dort verwendet werden, wo Sie einen Nullwert erwarten (NPE wird möglicherweise nie angezeigt, wenn Optional ordnungsgemäß verwendet wird). Wenn Sie beispielsweise eine Methode haben, die ein Personenobjekt erwartet, das möglicherweise nullwertfähig ist, möchten Sie die Methode möglicherweise wie folgt 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));}classPerson{privateString 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 das Telefon auch optional
In diesem Fall wird der Aufruf der Map-Funktion den zurückgegebenen Wert in Optional umbrechen und Folgendes ergeben:
Optional<Optional<String>>//And you may want Optional<String> instead, here comes flatMapvoid 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 eine Option auf, ohne sie mit isPresent () zu überprüfen, es sei denn, Sie können nicht ohne NullPointerExceptions leben.
Ich denke, dieses Beispiel wird wahrscheinlich von der Art Ihrer Antwort ablenken, weil Ihre Klasse Personmissbraucht Optional. Es ist gegen die Absicht der API, sie Optionalfür Mitglieder wie diese zu verwenden - siehe mail.openjdk.java.net/pipermail/jdk8-dev/2013-September/…
8bitjunkie
@ 8bitjunkie Vielen Dank für den Hinweis, es unterscheidet sich von Scala Option ..
SandeepGodara
6
Was mir geholfen hat, war ein Blick auf den Quellcode der beiden Funktionen.
Map - umschließt das Ergebnis mit einem optionalen Ergebnis.
public<U>Optional<U> map(Function<?super T,?extends U> mapper){Objects.requireNonNull(mapper);if(!isPresent())return empty();else{returnOptional.ofNullable(mapper.apply(value));//<--- wraps in an optional}}
Was meinst du mit flatMap"gibt das 'rohe' Objekt zurück"? flatMapGibt auch das zugeordnete Objekt zurück, das in ein "eingeschlossen" ist Optional. Der Unterschied besteht darin, dass im Fall von flatMapdie Mapper-Funktion das zugeordnete Objekt in das umschließt, Optionalwährend mapdas Objekt selbst eingeschlossen wird Optional.
Derek Mahar
@DerekMahar hat meine gelöscht, Sie müssen sie nicht erneut veröffentlichen, da Sie Ihren Kommentar richtig bearbeitet haben.
Maxxyme
3
Optional.map()::
Nimmt jedes Element und wenn der Wert existiert, wird er an die Funktion übergeben:
Jetzt hinzugefügt hat einen von drei Werten: trueoder falsein eine Option eingewickelt , falls optionalValuevorhanden, oder eine leere Option , falls nicht vorhanden .
Wenn Sie das Ergebnis, das Sie einfach verwenden können ifPresent(), nicht verarbeiten müssen, hat es keinen Rückgabewert:
optionalValue.ifPresent(results::add);
Optional.flatMap()::
Funktioniert ähnlich wie bei Streams. Glättet den Strom von Strömen. Mit dem Unterschied, dass der Wert, wenn er angezeigt wird, auf die Funktion angewendet wird. Andernfalls wird ein leeres optionales Element zurückgegeben.
Sie können es zum Erstellen optionaler Wertfunktionsaufrufe verwenden.
Angenommen, wir haben Methoden:
publicstaticOptional<Double> inverse(Double x){return x ==0?Optional.empty():Optional.of(1/ x);}publicstaticOptional<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 das inverse()oder das squareRoot()zurückgegeben wird Optional.empty(), ist das Ergebnis leer.
Dies wird nicht kompiliert. Beide Ausdrücke geben ein optionales <Double> anstelle des Double zurück, dem Sie das Ergebnis zuweisen.
JL_SO
@JL_SO du hast recht. Weil inverse den Optional<Double>Typ als Rückgabetyp hat.
Nazar_art
3
In Ordnung. Sie müssen 'flatMap' nur verwenden, wenn Sie mit verschachtelten Optionals konfrontiert sind . Hier ist das Beispiel.
publicclassPerson{privateOptional<Car> optionalCar;publicOptional<Car> getOptionalCar(){return optionalCar;}}publicclassCar{privateOptional<Insurance> optionalInsurance;publicOptional<Insurance> getOptionalInsurance(){return optionalInsurance;}}publicclassInsurance{privateString name;publicString getName(){return name;}}publicclassTest{// map cannot deal with nested OptionalspublicOptional<String> getCarInsuranceName(Person person){return person.getOptionalCar().map(Car::getOptionalInsurance)// ① leads to a Optional<Optional<Insurance>.map(Insurance::getName);// ②}}
Optional # map gibt wie Stream einen Wert zurück, der von Optional umschlossen wird. Deshalb erhalten wir eine verschachtelte Option - Optional<Optional<Insurance>. Und bei ② wollen wir es als Versicherungsinstanz abbilden, so geschah die Tragödie. Die Wurzel ist verschachtelte Optionals. Wenn wir den Kernwert unabhängig von den Muscheln erhalten können, werden wir es schaffen. Das macht flatMap.
Stream#flatMap
undOptional#flatMap
.Antworten:
Verwenden Sie
map
diese Option, wenn die Funktion das benötigte Objekt zurückgibt oderflatMap
wenn die Funktion ein zurückgibtOptional
. Beispielsweise:Beide print-Anweisungen drucken dasselbe.
quelle
[flat]Map
jemals die Mapping-Funktion mit einem aufrufeninput == null
? Ich verstehe, dassOptional
Sortcuts, wenn sie nicht vorhanden sind - das [JavaDoc] ( docs.oracle.com/javase/8/docs/api/java/util/… ) scheint dies zu unterstützen - " Wenn ein Wert vorhanden ist, wenden Sie an. . ".Optional.of(null)
ist einException
.Optional.ofNullable(null) == Optional.empty()
.Beide übernehmen eine Funktion vom Typ des Optionalen bis zu etwas.
map()
wendet die Funktion " wie sie ist " auf die Option an, die Sie haben:Was passiert, wenn Ihre Funktion eine Funktion von ist
T -> Optional<U>
?Ihr Ergebnis ist jetzt ein
Optional<Optional<U>>
!Darum geht
flatMap()
es: Wenn Ihre Funktion bereits eine zurückgibtOptional
,flatMap()
ist sie etwas intelligenter und umschließt sie nicht doppelt, sondern kehrt zurückOptional<U>
.Es ist die Zusammensetzung zweier funktionaler Redewendungen:
map
undflatten
.quelle
Hinweis: - Nachfolgend finden Sie eine Abbildung der Karten- und Flatmap-Funktion. Andernfalls ist Optional in erster Linie für die Verwendung als Rückgabetyp vorgesehen.
Wie Sie vielleicht bereits wissen, ist Optional eine Art Container, der ein einzelnes Objekt enthalten kann oder nicht. Daher kann es überall dort verwendet werden, wo Sie einen Nullwert erwarten (NPE wird möglicherweise nie angezeigt, wenn Optional ordnungsgemäß verwendet wird). Wenn Sie beispielsweise eine Methode haben, die ein Personenobjekt erwartet, das möglicherweise nullwertfähig ist, möchten Sie die Methode möglicherweise wie folgt schreiben:
Hier haben Sie einen String-Typ zurückgegeben, der automatisch in einen optionalen Typ eingeschlossen wird.
Wenn die Personenklasse so aussah, ist das Telefon auch optional
In diesem Fall wird der Aufruf der Map-Funktion den zurückgegebenen Wert in Optional umbrechen und Folgendes ergeben:
PS; Rufen Sie niemals die get-Methode (falls erforderlich) für eine Option auf, ohne sie mit isPresent () zu überprüfen, es sei denn, Sie können nicht ohne NullPointerExceptions leben.
quelle
Person
missbrauchtOptional
. Es ist gegen die Absicht der API, sieOptional
für Mitglieder wie diese zu verwenden - siehe mail.openjdk.java.net/pipermail/jdk8-dev/2013-September/…Was mir geholfen hat, war ein Blick auf den Quellcode der beiden Funktionen.
Map - umschließt das Ergebnis mit einem optionalen Ergebnis.
flatMap - gibt das ' raw' -Objekt zurück
quelle
flatMap
"gibt das 'rohe' Objekt zurück"?flatMap
Gibt auch das zugeordnete Objekt zurück, das in ein "eingeschlossen" istOptional
. Der Unterschied besteht darin, dass im Fall vonflatMap
die Mapper-Funktion das zugeordnete Objekt in das umschließt,Optional
währendmap
das Objekt selbst eingeschlossen wirdOptional
.Optional.map()
::Nimmt jedes Element und wenn der Wert existiert, wird er an die Funktion übergeben:
Jetzt hinzugefügt hat einen von drei Werten:
true
oderfalse
in eine Option eingewickelt , fallsoptionalValue
vorhanden, oder eine leere Option , falls nicht vorhanden .Wenn Sie das Ergebnis, das Sie einfach verwenden können
ifPresent()
, nicht verarbeiten müssen, hat es keinen Rückgabewert:Optional.flatMap()
::Funktioniert ähnlich wie bei Streams. Glättet den Strom von Strömen. Mit dem Unterschied, dass der Wert, wenn er angezeigt wird, auf die Funktion angewendet wird. Andernfalls wird ein leeres optionales Element zurückgegeben.
Sie können es zum Erstellen optionaler Wertfunktionsaufrufe verwenden.
Angenommen, wir haben Methoden:
Dann können Sie die Quadratwurzel der Inversen berechnen, wie:
oder, wenn Sie es vorziehen:
Wenn entweder das
inverse()
oder dassquareRoot()
zurückgegeben wirdOptional.empty()
, ist das Ergebnis leer.quelle
Optional<Double>
Typ als Rückgabetyp hat.In Ordnung. Sie müssen 'flatMap' nur verwenden, wenn Sie mit verschachtelten Optionals konfrontiert sind . Hier ist das Beispiel.
Optional # map gibt wie Stream einen Wert zurück, der von Optional umschlossen wird. Deshalb erhalten wir eine verschachtelte Option -
Optional<Optional<Insurance>
. Und bei ② wollen wir es als Versicherungsinstanz abbilden, so geschah die Tragödie. Die Wurzel ist verschachtelte Optionals. Wenn wir den Kernwert unabhängig von den Muscheln erhalten können, werden wir es schaffen. Das macht flatMap.Am Ende habe ich Ihnen Java 8 In Action dringend empfohlen , wenn Sie Java8 systematisch lernen möchten.
quelle