it-swarm.com.de

Wenn ich Optional.orElseGet () über Optional.orElse () verwenden muss

Ich brauche dazu eine klare Erklärung, obwohl ich diese link Unterschiede gelesen habe, aber keine klare Klarheit. Also irgendjemand erklärt mir dies kurz mit Code.

7
TVK

Ich glaube, ich fange an, deine Frage zu verstehen. Die Ausführungsreihenfolge mit Optional kann sich von der in der prozeduralen Programmierung verwendeten unterscheiden (das gleiche gilt für Java-Streams und anderen Code, der Lambdas verwendet).

Ich werde die zwei Beispiele aus Eugene Antwort verwenden:

    o1.orElse(new MyObject()); // 1055e4af 

Dies ist schlichtes altes Java: Es ist ein Aufruf an orElse(), wobei new MyObject() als Argument genommen wird. Das Argument wird also zuerst ausgewertet und ein neues MyObject erstellt. Diese wird dann an orElse() übergeben. orElse() prüft, ob ein Wert in Optional vorhanden ist. Wenn ja, wird der Wert zurückgegeben (das neu erstellte Objekt wird verworfen). Wenn nicht, wird das im Argument angegebene Objekt zurückgegeben. Dies war das einfachere Beispiel.

    o1.orElseGet(() -> {
        System.out.println("Should I see this");
        return new MyObject();
    });

Wieder haben wir einen Methodenaufruf mit einem Argument, und erneut wird das Argument zuerst ausgewertet. Das Lambda wird nur als Lieferant angelegt und übergeben. Der Code in { } wird noch nicht ausgeführt (Sie sehen auch keinen Should I see this in der Ausgabe von Eugene). orElseGet prüft erneut, ob in Optional ein Wert vorhanden ist. Wenn ja, wird der Wert zurückgegeben und der übergebene Lieferant wird ignoriert. Ist dies nicht der Fall, wird der Lieferant aufgerufen, und der Code in { } wird ausgeführt, um den Wert zu erhalten, der von orElseGet() zurückgegeben werden soll.

Im ersten Fall kann man sagen, dass MyObject erstellt und verschwendet wird. Im zweiten wird ein Supplier erstellt und verschwendet. Was Sie als Gegenleistung erhalten, ist in beiden Fällen knapper und nullzeigersicherer Code. So oft ist es nicht wichtig, welchen Sie wählen. Wenn die Erstellung von MyObject kostspielig ist oder unerwünschte Nebenwirkungen hat, möchten Sie natürlich die zweite Version, in der das Objekt nur erstellt wird, wenn Sie dazu aufgefordert werden, und niemals verschwendet wird. Eugene erwähnt in einem Kommentar den Fall, in dem das zurückgegebene Objekt von einem Datenbankaufruf stammt. Datenbankaufrufe sind in der Regel so zeitaufwändig, dass Sie nicht zu keinem Zweck einen Anruf tätigen möchten.

29
Ole V.V.

Wie wäre es mit einem Beispiel:

static class MyObject {
    public MyObject() {
        System.out.println("Creating one..." + this);
    }
}

Und einige Verwendung:

  Optional<MyObject> o1 = Optional.of(new MyObject()); // 7382f612

    o1.orElse(new MyObject()); // 1055e4af 
    o1.orElseGet(() -> {
        System.out.println("Should I see this");
        return new MyObject();
    });

Und etwas Ausgabe:

 Creating one... [email protected]
 Creating one... [email protected]

Falls Optional einen Wert hat ; orElse wird noch aufgerufen, aber nicht verwendet. Auf die widersprüchliche orElseGet wird nicht aufgerufen.

Berücksichtigen Sie den Fall, wenn das Erstellen des Objekts teuer ist. welches wirst du benutzen?

Es ist eigentlich einfacher zu verstehen, denke ich, wenn Sie in den Code schauen:

public T orElseGet(Supplier<? extends T> supplier) {
    return value != null ? value : supplier.get();
}
12
Eugene

Wie beantwortet hier , sollten Sie den zweiten Ansatz in Betracht ziehen, wenn die benötigte Ressource teuer ist, um zu erhalten.

// Always get heavy resource
getResource(resourceId).orElse(getHeavyResource()); 

// Get heavy resource when required.
getResource(resourceId).orElseGet(() -> getHeavyResource()) 
1
nxhoaf