In Java 8 möchte ich etwas mit einem Optional
Objekt tun, wenn es vorhanden ist, und etwas anderes tun, wenn es nicht vorhanden ist.
if (opt.isPresent()) {
System.out.println("found");
} else {
System.out.println("Not found");
}
Dies ist jedoch kein "funktionaler Stil".
Optional
hat eine ifPresent()
Methode, aber ich kann keine orElse()
Methode verketten.
Daher kann ich nicht schreiben:
opt.ifPresent( x -> System.out.println("found " + x))
.orElse( System.out.println("NOT FOUND"));
Als Antwort auf @assylias denke ich nicht, dass dies Optional.map()
für den folgenden Fall funktioniert:
opt.map( o -> {
System.out.println("while opt is present...");
o.setProperty(xxx);
dao.update(o);
return null;
}).orElseGet( () -> {
System.out.println("create new obj");
dao.save(new obj);
return null;
});
In diesem Fall opt
aktualisiere ich , wenn vorhanden, seine Eigenschaft und speichere in der Datenbank. Wenn es nicht verfügbar ist, erstelle ich eine neue obj
und speichere sie in der Datenbank.
Beachten Sie in den beiden Lambdas, dass ich zurückkehren muss null
.
Aber wenn opt
vorhanden, werden beide Lambdas ausgeführt. obj
wird aktualisiert und ein neues Objekt wird in der Datenbank gespeichert. Dies liegt am return null
im ersten Lambda. Und orElseGet()
wird weiterhin ausgeführt.
quelle
return null;
mitreturn o;
(beide). Ich habe jedoch das starke Gefühl, dass Sie am falschen Ort arbeiten. Sie sollten an der Stelle arbeiten, an der das hergestellt wurdeOptional
. An dieser Stelle sollte es eine Möglichkeit geben, die gewünschte Operation ohne Zwischenprodukt durchzuführenOptional
.ifPresent
widerspricht dem. Alle anderen Methoden beziehen sich auf den Wert und nicht auf Aktionen.Antworten:
Für mich ist die Antwort von @Dane White OK, zuerst mochte ich Runnable nicht, aber ich konnte keine Alternativen finden, hier eine andere Implementierung, die ich mehr bevorzugte
Dann :
Update 1:
Die obige Lösung für die traditionelle Art der Entwicklung, wenn Sie den Wert haben und ihn verarbeiten möchten, aber was ist, wenn ich die Funktionalität und die Ausführung definieren möchte, überprüfen Sie unten die Verbesserung.
Dann könnte verwendet werden als:
In diesem neuen Code haben Sie 3 Dinge:
Übrigens ist sein Name jetzt aussagekräftiger, er ist tatsächlich Verbraucher>
quelle
Wenn Sie Java 9+ verwenden, können Sie folgende
ifPresentOrElse()
Methode verwenden:quelle
Java 9 wird eingeführt
ifPresentOrElse führt, wenn ein Wert vorhanden ist, die angegebene Aktion mit dem Wert aus, andernfalls führt die angegebene leere Aktion aus.
Siehe ausgezeichnet Optional in Java 8 Spickzettel .
Es bietet alle Antworten für die meisten Anwendungsfälle.
Kurze Zusammenfassung unten
ifPresent () - etwas tun, wenn Optional eingestellt ist
filter () - bestimmte optionale Werte ablehnen (herausfiltern).
map () - Wert transformieren, falls vorhanden
orElse () / orElseGet () - leer werden Optional auf Standard T.
orElseThrow () - träge Ausnahmen auf leer werfen Optional
quelle
map
, aber es ist ein bisschen seltsam, nach einer funktionalen Lösung zu fragen, damit Sie einen DAO anrufen können. Mir scheint, es wäre sinnvoller, das aktualisierte / neue Objekt aus diesemmap.orElse
Block zurückzugeben und dann das zu tun, was Sie mit dem zurückgegebenen Objekt tun müssen.map
konzentrieren Sie sich auf den Stream selbst und sind nicht dazu gedacht, "Dinge mit einem anderen Objekt zu tun, abhängig vom Status dieses Elements im Stream". Gut zu wissen, dassifPresentOrElse
in Java 9 hinzugefügt wird.Eine Alternative ist:
Ich denke nicht, dass es die Lesbarkeit verbessert.
Oder verwenden Sie, wie von Marko vorgeschlagen, einen ternären Operator:
quelle
new Object();
in deinem ersten Lambda zurückkehren, aber um ehrlich zu sein, wird das sehr hässlich. Ich würde mich an ein if / else für Ihr aktualisiertes Beispiel halten.map
nurOptional
zur Verkettung zurückkehren, wird der Code schwieriger zu verstehen, währendmap
davon ausgegangen wird, dass er buchstäblich auf etwas abgebildet wird.Eine andere Lösung wäre, Funktionen höherer Ordnung wie folgt zu verwenden
quelle
value -> () -> syso
Teil bedeutet.String result = opt.map(value -> "withOptional").orElse("without optional");
Es gibt keine großartige Möglichkeit, dies sofort zu tun. Wenn Sie Ihre Cleaner-Syntax regelmäßig verwenden möchten, können Sie eine Utility-Klasse erstellen, um Folgendes zu unterstützen:
Dann können Sie einen statischen Import an anderer Stelle verwenden, um eine Syntax zu erhalten, die genau dem entspricht, wonach Sie suchen:
quelle
Optional.ifPresentOrElse()
wurde zu JDK 9 hinzugefügt.Wenn Sie nur Java 8 oder niedriger verwenden können:
1) Wenn Sie bisher nicht
spring-data
den besten Weg haben, ist:Jetzt weiß ich, dass es für jemanden nicht so lesbar und sogar schwer zu verstehen ist, aber für mich persönlich sieht es gut aus und ich sehe keinen anderen schönen fließenden Weg für diesen Fall.
2) Wenn Sie Glück haben und
spring-data
den besten Weg nutzen können , ist Optionals # ifPresentOrElse :Wenn Sie Java 9 verwenden können, sollten Sie auf jeden Fall Folgendes wählen:
quelle
Das beschriebene Verhalten kann mit erreicht werden Vavr (früher bekannt als Javaslang) erreicht werden, einer objektfunktionalen Bibliothek für Java 8+, die die meisten Scala-Konstrukte implementiert (Scala ist eine ausdrucksstärkere Sprache mit einem wesentlich umfangreicheren Typsystem, das auf JVM basiert). Es ist eine sehr gute Bibliothek, die Sie zu Ihren Java-Projekten hinzufügen können, um reinen Funktionscode zu schreiben.
Vavr bietet die
Option
Monade, die Funktionen für die Arbeit mit dem Optionstyp bereitstellt , z.fold
: um den Wert der Option in beiden Fällen zuzuordnen (definiert / leer)onEmpty
: Ermöglicht die Ausführung einerRunnable
When-Option, wenn diese leer istpeek
: Ermöglicht die Verwendung des Werts der Option (falls definiert).Serializable
im Gegenteil,Optional
was bedeutet, dass Sie es sicher als Methodenargument und Instanzmitglied verwenden können.Option folgt den Monadengesetzen, die sich von der optionalen "Pseudo-Monade" von Java unterscheiden, und bietet eine umfangreichere API. Und natürlich können Sie es aus einem Java-Optional (und umgekehrt) machen:
Option.ofOptional(javaOptional)
–Vavr konzentriert sich auf Interoperabilität.Zum Beispiel gehen:
Weiterführende Literatur
Null Referenz, der Milliarden-Dollar-Fehler
NB Dies ist nur ein sehr kleines Beispiel für das, was Vavr bietet (Mustervergleich, Streams, auch bekannt als faul bewertete Listen, monadische Typen, unveränderliche Sammlungen, ...).
quelle
Eine andere Lösung könnte sein:
So verwenden Sie es:
Oder falls Sie im Falle des entgegengesetzten Anwendungsfalls wahr sind:
Dies sind die Zutaten:
Die "kosmetisch" verbesserte Funktionsschnittstelle.
Und die optionale Wrapper-Klasse zur Verbesserung:
Dies sollte den Trick tun und könnte als grundlegende Vorlage für den Umgang mit solchen Anforderungen dienen.
Die Grundidee hier folgt. In einer nicht funktionalen Programmierwelt würden Sie wahrscheinlich eine Methode implementieren, die zwei Parameter verwendet, wobei der erste eine Art ausführbarer Code ist, der ausgeführt werden sollte, wenn der Wert verfügbar ist, und der andere Parameter der ausführbare Code ist, der ausgeführt werden sollte, wenn der Wert ist nicht verfügbar. Zur besseren Lesbarkeit können Sie die Funktion von zwei Parametern mithilfe von curring in zwei Funktionen mit jeweils einem Parameter aufteilen. Das habe ich hier im Grunde getan.
Hinweis: Opt bietet auch den anderen Anwendungsfall, in dem Sie einen Code ausführen möchten, falls der Wert nicht verfügbar ist. Dies könnte auch über Optional.filter.stuff erfolgen, aber ich fand dies viel besser lesbar.
Ich hoffe, das hilft!
Gute Programmierung :-)
quelle
Falls Sie den Wert speichern möchten:
quelle
Angenommen, Sie haben eine Liste und vermeiden das
isPresent()
Problem (im Zusammenhang mit Optionen), mit dem Sie.iterator().hasNext()
überprüfen können, ob es nicht vorhanden ist.quelle