Ich versuche den Unterschied zwischen Optional<T>.orElse()
und Optional<T>.orElseGet()
Methoden zu verstehen .
Die Beschreibung für die orElse()
Methode lautet "Geben Sie den Wert zurück, falls vorhanden, andernfalls geben Sie einen anderen zurück."
Die Beschreibung für die orElseGet()
Methode lautet "Geben Sie den Wert zurück, falls vorhanden, rufen Sie andernfalls den anderen auf und geben Sie das Ergebnis dieses Aufrufs zurück."
Die orElseGet()
Methode verwendet eine Lieferantenfunktionsschnittstelle, die im Wesentlichen keine Parameter akzeptiert und zurückgibt T
.
In welcher Situation müssten Sie verwenden orElseGet()
? Wenn Sie eine Methode haben, T myDefault()
warum würden Sie das nicht einfach tun optional.orElse(myDefault())
als optional.orElseGet(() -> myDefault())
?
Es scheint nicht so, orElseGet()
als würde die Ausführung des Lambda-Ausdrucks auf einen späteren Zeitpunkt verschoben oder so. Worum geht es also? (Ich hätte gedacht , dass es sinnvoller wäre , wenn es zu einem sichereren zurückgegeben , Optional<T>
die get()
nie wirft NoSuchElementException
und isPresent()
immer wieder wahr ... aber offenbar ist es nicht, es gerade Rückkehr T
wie orElse()
).
Gibt es einen anderen Unterschied, den ich vermisse?
orElseGet
, ruft der Lieferant nur an, wenn kein Wert vorhanden ist.orElse()
dermyDefault()
Methode wird also immer noch aufgerufen, aber ihr Rückgabewert wird einfach nicht verwendet.orElseGet()
einigen schwerwiegenden Fehlern führen kann: medium.com/alphadev-Antworten:
Nehmen Sie diese beiden Szenarien:
Wenn
opt
kein Wert enthalten ist, sind die beiden tatsächlich gleichwertig. Aber wennopt
es einen Wert enthält, wie vieleFoo
Objekte werden erstellt?Ps: Natürlich wäre in diesem Beispiel der Unterschied wahrscheinlich nicht messbar, aber wenn Sie Ihren Standardwert beispielsweise von einem Remote-Webdienst oder von einer Datenbank beziehen müssen, wird er plötzlich sehr wichtig.
quelle
Foo
Objekt erstellt, im ersten Fall wird es erstellt, es wird jedoch nicht verwendet, wenn sich ein Wert in der befindetOptional
.System.out.println()
handelt es sich nicht um eine Berechnung, sondern um eine Aussage, die einen beobachtbaren Nebeneffekt hervorruft. Und ich habe bereits gesagt, dass beobachtbare Nebenwirkungen Optimierungen behindern (der Konsolenausgabestream ist eine externe Ressource).Kurze Antwort:
Optional.isPresent()
WertOptional.isPresent() == false
In echtem Code sollten Sie den zweiten Ansatz in Betracht ziehen, wenn die Beschaffung der erforderlichen Ressource teuer ist .
Weitere Details finden Sie im folgenden Beispiel mit dieser Funktion:
Der Unterschied ist wie folgt:
Wann
optional.isPresent() == false
gibt es keinen Unterschied zwischen zwei Möglichkeiten. Wenn jedochoptional.isPresent() == true
,orElse()
ruft immer die nachfolgende Funktion auf, ob Sie es wollen oder nicht.Schließlich wird der folgende Testfall verwendet:
Ergebnis:
Code:
quelle
Optional.isPresent() == false
stattdessen (falsch, nicht wahr) seinOptional.orElse
die StaatenIf a value is present, returns the value, otherwise returns other
dieses Verhalten implizieren können ...orElse()
sich das ähnlich wiefinally
imtry-catch
Ausdruck verhalten . Hab ich recht?Ich griff hier nach dem Problem, das Kudo erwähnte.
Ich teile meine Erfahrungen für andere.
orElse
oderorElseGet
das ist die Frage:druckt
orElse
wertet den Wert von B () in Abhängigkeit vom Wert des optionalen aus. AlsoorElseGet
ist faul.quelle
B()
an eine Methode mit dem Namen übergebenorElse()
oderabc()
diese keinen Unterschied macht,B()
wird sie ausgewertet.or
Präfix führt Entwickler (einschließlich meiner selbst, als ich das Problem stellte) in die Irre, zu denken, dass es sich um eine Kurzschlussoperation handelt, da wir dies unter booleschen Bedingungen gewohnt sind. Es ist jedoch nicht so, dass es sich nur um einen Methodennamen handelt,or
dessen PräfixOptional
lautet. Daher werden seine Argumente ausgewertet, unabhängig davon, ob sie einen Wert enthalten oder nicht. Es ist bedauerlich, dass die Benennung verwirrend ist und wir nichts dagegen tun können.Ich würde sagen, der größte Unterschied zwischen
orElse
undorElseGet
kommt, wenn wir etwas bewerten wollen, um den neuen Wert in derelse
Bedingung zu erhalten.Betrachten Sie dieses einfache Beispiel -
Lassen Sie uns nun das obige Beispiel in die Verwendung
Optional
mitorElse
, umwandeln.Lassen Sie uns nun das obige Beispiel in die Verwendung
Optional
mitorElseGet
, umwandeln.Beim
orElse
Aufrufen wird dasapicall().value
ausgewertet und an die Methode übergeben. Während beiorElseGet
der Auswertung nur, wenn dieoldValue
leer ist.orElseGet
ermöglicht eine verzögerte Auswertung.quelle
Das folgende Beispiel soll den Unterschied demonstrieren:
Die Antwort erscheint auch in den Dokumenten.
public T orElseGet(Supplier<? extends T> other)
::Das
Supplier
wird nicht aufgerufen, wenn dieOptional
Geschenke. wohingegen,public T orElse(T other)
::Wenn
other
es sich um eine Methode handelt, die eine Zeichenfolge zurückgibt, wird diese aufgerufen, ihr Wert wird jedoch nicht zurückgegeben, falls die ZeichenfolgeOptional
vorhanden ist.quelle
Der Unterschied ist ziemlich subtil und wenn Sie nicht viel Aufmerksamkeit schenken, werden Sie es falsch verwenden.
Der beste Weg , den Unterschied zwischen verstehen
orElse()
undorElseGet()
wird , dassorElse()
wird immer dann ausgeführt werden , wenn derOptional<T>
ist null oder nicht , aberorElseGet()
wird nur dann ausgeführt werden , wennOptional<T>
ist null .Die Wörterbuchbedeutung von orElse ist : - den Teil aus, wenn etwas nicht vorhanden ist, aber hier widerspricht es, siehe das folgende Beispiel:
Benchmarks :
Hoffe, es klärt die Zweifel von Leuten wie mir, die das grundlegende Beispiel wollen :)
quelle
Überprüfen Sie zunächst die Deklaration beider Methoden.
1) OrElse: Führen Sie die Logik aus und übergeben Sie das Ergebnis als Argument.
2) OrElseGet: Führen Sie die Logik aus, wenn der Wert im optionalen Wert null ist
Einige Erklärungen zur obigen Erklärung: Das Argument "Optional.orElse" wird immer ausgeführt, unabhängig vom Wert des Objekts in optional (null, leer oder mit Wert). Beachten Sie bei der Verwendung von „Optional.orElse“ immer den oben genannten Punkt. Andernfalls kann die Verwendung von „Optional.orElse“ in der folgenden Situation sehr riskant sein.
Risiko-1) Protokollierungsproblem: Wenn der Inhalt in orElse eine Protokollanweisung enthält: In diesem Fall werden Sie ihn jedes Mal protokollieren.
Risiko-2) Leistungsproblem: Wenn der Inhalt in orElse zeitintensiv ist: Zeitintensiver Inhalt kann ein beliebiger DB-Aufruf für E / A-Vorgänge, ein API-Aufruf oder das Lesen von Dateien sein. Wenn wir solchen Inhalt in orElse () einfügen, führt das System einen Code aus, der keinen Nutzen hat.
Risiko-3) Unzulässiger Status oder Fehler Problem : Wenn der Inhalt in orElse einen Objektstatus mutiert: Wir verwenden möglicherweise dasselbe Objekt an einer anderen Stelle, beispielsweise in der Funktion Optional.map, und es kann zu einem kritischen Fehler kommen.
Wann können wir dann mit orElse () gehen? Verwenden Sie lieber orElse, wenn der Standardwert ein konstantes Objekt ist, enum. In allen oben genannten Fällen können wir Optional.orElseGet () (das nur ausgeführt wird, wenn Optional einen nicht leeren Wert enthält) anstelle von Optional.orElse () verwenden. Warum?? In orElse übergeben wir den Standardergebniswert, in orElseGet übergeben wir Supplier, und die Methode des Supplier wird nur ausgeführt, wenn der Wert in Optional null ist.
Wichtige Erkenntnisse daraus:
Ich habe dies in Punkt 2 ( "Optional.map/Optional.orElse"! = "If / else" ) in meinem mittleren Blog erklärt. Verwenden Sie Java8 als Programmierer und nicht als Codierer
quelle
Berücksichtigt man den folgenden Code:
wenn wir bekommen
value
auf diese Weise:Optional.<String>ofNullable(null)
Es gibt keinen Unterschied zwischen orElseGet () und OrElse (), aber wenn wir bekommenvalue
auf diese Weise:Optional.<String>ofNullable("test")
,orelesMethod()
inorElseGet()
nicht in Anspruch genommen werden , aber inorElse()
es wird aufgerufen,quelle