Betrachten Sie den folgenden Anwendungsfall einer Anwendung mit einem Benutzerpräferenzsystem:Optional ist `orElse` lazy evaluation scheitern führt zu Leistungseinbußen
Wir wollen MyFlag
den Bool Wert der Vorzug erhalten.
Im besten Fall wollen wir es aus den Einstellungen des aktuellen Benutzers. Wenn das nicht funktioniert, möchten wir MyFlag
von den Standardeinstellungen erhalten.
Wenn sogar das fehlschlägt, werfen.
Die Einstellungen sind auf einem Server. Diese Verbindung ist langsam und kann fehlschlagen.
Das Abrufen der Einstellungen und das Abrufen der Präferenz können ebenfalls fehlschlagen.
lässt So verwenden javas Optionals:
public static boolean getMyFlag()throws NoSuchElementException
{
return getUserOrDefaultPreference("MY_FLAG");
}
private Boolean getUserOrDefaultPreference(String preferenceName) throws NoSuchElementException
{
return Optional.ofNullable(getConnection()) // get slow connection
.map(connection -> connection.getUserSettings()) // get user settings
.map(settings -> settings.getPref(preferenceName)) // return preference
.orElse(slowlyGetDefaultPreference(preferenceName)); // or else return default value
}
private Boolean slowlyGetDefaultPreference(String preferenceName) throws NoSuchElementException
{
return Optional.ofNullable(getConnection()) // get slow connection
.map(connection -> connection.getDefaultSettings()) // get default settings
.map(settings -> settings.getPref(preferenceName)) // return preference
.orElseThrow(() -> new NoSuchElementException()); // if any of the above fails throw
}
Problem hier ist, dass die Verbindung sehr langsam sein kann. Wenn .orElse(slowlyGet...);
aufgerufen wird, wird die Funktion slowlyGetDefaultPreference()
zuerst ausgewertet, unabhängig davon, ob mein Optional leer ist oder einen Wert hat. Dies ist eine Leistungseinbuße, die ich vermeiden muss.
Ich versuchte mit einem Lieferanten über .orElseGet(() -> slowlytGet..)
, aber das führte zu dem gleichen Problem.
So ist meine einzige Zuflucht ist das hässliche isPresent()
anti-Muster, das aus einer Ablesbarkeit Sicht die gesamten Optional Strömungs ruiniert:
private Boolean getUserOrDefaultPreference(String preferenceName) throws NoSuchElementException
{
Optional<Boolean> opt = Optional.ofNullable(getConnection())
.map(connection -> connection.getUserSettings())
.map(settings -> settings.getPref(preferenceName));
if(opt.isPresent())
{
return opt.get();
}
else
{
slowlyGetDefaultPreference(preferenceName));
}
}
Das gleiche gilt die Ausnahme für das Werfen, wie ich will nicht das bezahlen Baukosten.
Fehle ich hier etwas oder ist das die einzige Lösung?
'orElseGet' sollte genauso funktionieren wie das letzte Beispiel, ich verstehe nicht, warum Sie sagen, es hat das gleiche Problem wie 'orElse' – Magnus
@Magnus Ich habe den Code mit dem Debugger durchgeblättert und konnte sehen, dass für' orElse' 'getSlow ..()' aufgerufen wurde. –
Ja, weil die Auswertung von 'orElseGet' nur aufgerufen wird, wenn eine Funktion vor' orElseGet' ein Null-Objekt hat. Aber wenn Sie 'orElse' verwenden, heißt immer – MateuszW90