Java Optional - orElse () vs orElseGet ()

1. Einleitung

Die API von Optional verfügt normalerweise über zwei Methoden, die Verwirrung stiften können: orElse () und orElseGet () .

In diesem kurzen Tutorial werden wir uns den Unterschied zwischen diesen beiden ansehen und herausfinden, wann jeder verwendet werden muss.

2. Unterschriften

Beginnen wir zunächst mit den Grundlagen, indem wir uns ihre Signaturen ansehen:

public T orElse(T other) public T orElseGet(Supplier other)

Es ist klar, dass orElse () einen beliebigen Parameter vom Typ T verwendet, während orElseGet () eine funktionale Schnittstelle vom Typ Supplier akzeptiert , die ein Objekt vom Typ T zurückgibt .

Nun, basierend auf ihren Javadocs:

  • orElse () : Gibt den Wert zurück, falls vorhanden, andernfalls den Wert other
  • orElseGet (): Gibt den Wert zurück, falls vorhanden. Andernfalls rufen Sie other auf und geben das Ergebnis des Aufrufs zurück

3. Unterschiede

Es ist leicht, durch diese vereinfachten Definitionen ein wenig verwirrt zu werden. Lassen Sie uns also etwas tiefer gehen und einige tatsächliche Verwendungsszenarien betrachten.

3.1. orElse ()

Angenommen, wir haben unseren Logger richtig konfiguriert, beginnen wir mit dem Schreiben eines einfachen Codes:

String name = Optional.of("baeldung") .orElse(getRandomName());

Beachten Sie, dass getRandomName () eine Methode ist, die einen zufälligen Namen aus einer Liste von Namen zurückgibt :

public String getRandomName() { LOG.info("getRandomName() method - start"); Random random = new Random(); int index = random.nextInt(5); LOG.info("getRandomName() method - end"); return names.get(index); }

Bei der Ausführung unseres Codes finden Sie die folgenden Meldungen in der Konsole:

getRandomName() method - start getRandomName() method - end

Der Variable Name wird halten „baeldung“ am Ende der Codeausführung.

Damit können wir leicht schließen, dass der Parameter von orElse () auch dann ausgewertet wird, wenn eine nicht leere Option vorhanden ist .

3.2. orElseGet ()

Versuchen wir nun, ähnlichen Code mit orElseGet () zu schreiben :

String name = Optional.of("baeldung") .orElseGet(() -> getRandomName());

Der obige Code ruft nicht die Methode getRandomName () auf .

Denken Sie daran (aus dem Javadoc), dass die als Argument übergebene S upplier- Methode nur ausgeführt wird, wenn kein optionaler Wert vorhanden ist.

Die Verwendung von orElseGet () für unseren Fall spart uns daher einige Zeit bei der Berechnung eines zufälligen Namens .

4. Messung der Auswirkungen auf die Leistung

Um auch die Leistungsunterschiede zu verstehen, verwenden wir JMH und sehen einige tatsächliche Zahlen:

@Benchmark @BenchmarkMode(Mode.AverageTime) public String orElseBenchmark() { return Optional.of("baeldung").orElse(getRandomName()); }

Und orElseGet () :

@Benchmark @BenchmarkMode(Mode.AverageTime) public String orElseGetBenchmark() { return Optional.of("baeldung").orElseGet(() -> getRandomName()); }

Bei der Ausführung unserer Benchmark-Methoden erhalten wir:

Benchmark Mode Cnt Score Error Units orElseBenchmark avgt 20 60934.425 ± 15115.599 ns/op orElseGetBenchmark avgt 20 3.798 ± 0.030 ns/op

Wie wir sehen können, können die Auswirkungen auf die Leistung selbst in einem so einfachen Anwendungsfall erheblich sein.

Die Zahlen über geringfügig variieren jedoch orElseGet () hat sich deutlich besser als OrElse () für uns ein besonderes Beispiel.

Afterall, OrElse () beinhaltet Berechnung von getRandomName () Methode für jeden Durchlauf.

5. Was ist wichtig?

Neben den Leistungsaspekten sind weitere Faktoren zu berücksichtigen:

  • Was wäre, wenn die Methode eine zusätzliche Logik ausführen würde? ZB einige DB-Einfügungen oder Aktualisierungen vornehmen
  • Auch wenn wir dem Parameter orElse () ein Objekt zuweisen :
    String name = Optional.of("baeldung").orElse("Other")

    Wir erstellen immer noch "Andere" Objekte ohne Grund

Aus diesem Grund ist es wichtig, dass wir je nach Bedarf eine sorgfältige Entscheidung zwischen orElse () und orElseGet () treffen. Standardmäßig ist es sinnvoller, jedes Mal orElseGet () zu verwenden, es sei denn, das Standardobjekt ist bereits erstellt und direkt zugänglich .

6. Fazit

In diesem Artikel haben wir die Nuancen zwischen den optionalen Methoden orElse () und OrElseGet () kennengelernt . Wir haben auch festgestellt, dass solche einfachen Konzepte manchmal eine tiefere Bedeutung haben können.

Wie immer finden Sie den vollständigen Quellcode auf Github.