Richtige Verwendung von Optional.ifPresent()

Lesezeit: 5 Minuten

Benutzer-Avatar
Strahlmann

Ich versuche das zu verstehen ifPresent() Methode der Optional API in Java 8.

Ich habe eine einfache Logik:

Optional<User> user=...
user.ifPresent(doSomethingWithUser(user.get()));

Dies führt jedoch zu einem Kompilierungsfehler:

ifPresent(java.util.functionError:(186, 74) java: 'void' type not allowed here)

Natürlich kann ich so etwas machen:

if(user.isPresent())
{
  doSomethingWithUser(user.get());
}

Aber das ist genau wie ein überladen null überprüfen.

Wenn ich den Code in diesen ändere:

 user.ifPresent(new Consumer<User>() {
            @Override public void accept(User user) {
                doSomethingWithUser(user.get());
            }
        });

Der Code wird immer schmutziger, was mich dazu bringt, zum alten zurückzukehren null überprüfen.

Irgendwelche Ideen?

Benutzer-Avatar
JB Niet

Optional<User>.ifPresent() nimmt ein Consumer<? super User> als argument. Sie übergeben ihm einen Ausdruck, dessen Typ void ist. Das kompiliert also nicht.

Ein Consumer soll als Lambda-Ausdruck implementiert werden:

Optional<User> user = ...
user.ifPresent(theUser -> doSomethingWithUser(theUser));

Oder noch einfacher, mit einer Methodenreferenz:

Optional<User> user = ...
user.ifPresent(this::doSomethingWithUser);

Das ist im Grunde dasselbe wie

Optional<User> user = ...
user.ifPresent(new Consumer<User>() {
    @Override
    public void accept(User theUser) {
        doSomethingWithUser(theUser);
    }
});

Die Idee ist, dass die doSomethingWithUser() Methodenaufruf wird nur ausgeführt, wenn der Benutzer anwesend ist. Ihr Code führt den Methodenaufruf direkt aus und versucht, sein void-Ergebnis an zu übergeben ifPresent().

  • Dieser Code wird unübersichtlich. Eine Nullprüfung wird viel sauberer sein. Glaubst du nicht, dass doSomethingWithUser keine statische Methode ist?

    – Strahlmann

    15. Juni 2014 um 9:59 Uhr

  • Welcher Code? Diejenige, die Sie verwenden sollten, ist die zweite, die die Instanzmethode (dh nicht-statisch) doSomethingWithUser() aufruft. Ich sehe nicht, wie es unübersichtlich ist. Der letzte Code soll Ihnen das Äquivalent des Lambda in einer Prä-Lambda-Welt erklären. Verwenden Sie es nicht.

    – JB Nizet

    15. Juni 2014 um 10:01 Uhr

  • Ja, aber Sie sind möglicherweise an anonyme Klassen gewöhnt und verstehen daher, was das Lambda tut, indem Sie ein anonymes Klassenäquivalent sehen. Das ist der Punkt.

    – JB Nizet

    15. Juni 2014 um 10:21 Uhr

  • Sie müssen nichts ändern. Lassen Sie es so wie es ist und verwenden Sie das zweite Beispiel: user.ifPresent(this::doSomethingWithUser);

    – JB Nizet

    15. Juni 2014 um 15:36 Uhr

  • @rayman Wenn Sie eine Funktion haben, die zurückgibt Optional<User> es besteht oft keine Notwendigkeit, es in einer lokalen Variablen zu speichern. Verketten Sie einfach die Methodenaufrufe: funcThatMightReturnUser().ifPresent(this::doSomethingWithUser);

    – Stuart Marks

    15. Juni 2014 um 17:45 Uhr

Benutzer-Avatar
cst1992

Zusätzlich zur Antwort von @JBNizet ist mein allgemeiner Anwendungsfall für ifPresent ist zu kombinieren .isPresent() und .get():

Alter Weg:

Optional opt = getIntOptional();
if(opt.isPresent()) {
    Integer value = opt.get();
    // do something with value
}

Neuer Weg:

Optional opt = getIntOptional();
opt.ifPresent(value -> {
    // do something with value
})

Das ist für mich intuitiver.

  • aber was auch immer drinnen ist, sollte ungültig sein, weil alles, was du von drinnen zurückgibst, verloren ist

    – wert

    15. April 2021 um 18:59 Uhr

  • @valik Ja, das ist so. Sie sollten nicht erwarten, von dort einen Wert zurückzugeben; es ist eher wie “tu dies”.

    – cst1992

    16. April 2021 um 5:20 Uhr


  • Das ist für mich intuitiver. – insbesondere unter Berücksichtigung, dass Sie diesen Wert hier NICHT zuweisen können, da dieses “alles” innerhalb von Lambda endgültig sein muss. Was für ein großer Vorteil dann

    – Andrej M. Stepanow

    14. Mai um 22:16 Uhr

Benutzer-Avatar
schlebe

Warum komplizierten Code schreiben, wenn es auch einfach geht?

In der Tat, wenn Sie die unbedingt verwenden werden Optional Klasse, der einfachste Code ist der, den Sie bereits geschrieben haben …

if (user.isPresent())
{
    doSomethingWithUser(user.get());
}

Dieser Code hat die Vorteile des Seins

  1. lesbar
  2. einfach zu debuggen (Haltepunkt)
  3. nicht knifflig

Nur weil Oracle das hinzugefügt hat Optional Klasse in Java 8 bedeutet nicht, dass diese Klasse in allen Situationen verwendet werden muss.

  • Der Hauptvorteil der Verwendung von ifPresent besteht darin, dass Sie get() nicht mehr manuell aufrufen müssen. Der manuelle Aufruf von get() ist fehleranfällig, da man leicht vergisst, isPresent zuerst zu überprüfen, aber es ist unmöglich, dass man es vergisst, wenn man ifPresent verwendet

    – dustinroepsch

    2. Dezember 2019 um 21:47 Uhr

  • Ok und jedes Mal, wenn Sie das ‘Benutzer’-Objekt verwenden, sollten Sie .ifPresent() aufrufen. Der Code wird schnell unlesbar, weil Sie .ifPresent() zu lange lesen!

    – schlebe

    2. Dezember 2019 um 22:34 Uhr

  • Der Hauptvorteil der Verwendung von ifPresent ist das überhaupt nicht – es soll nur mit einem anderen Argument, Verbraucher, arbeiten, das nicht in allen Fällen anwendbar ist

    – Andrej M. Stepanow

    14. Mai um 22:18 Uhr

Benutzer-Avatar
Alexander Podkutin

Sie können die Methodenreferenz wie folgt verwenden:

user.ifPresent(ClassNameWhereMethodIs::doSomethingWithUser);

Methode ifPresent() erhalten Consumer Objekt als Parameter und (von JavaDoc): “Wenn ein Wert vorhanden ist, rufe den angegebenen Consumer mit dem Wert auf.” Wert ist Ihre Variable user.

Oder wenn diese Methode doSomethingWithUser ist in dem User Klasse und das ist es nicht statickönnen Sie die Methodenreferenz wie folgt verwenden:

user.ifPresent(this::doSomethingWithUser);

Verwenden Sie flatMap. Wenn ein Wert vorhanden ist, gibt flatMap einen sequentiellen Stream zurück, der nur diesen Wert enthält, ansonsten einen leeren Stream. Es besteht also keine Notwendigkeit zu verwenden ifPresent() . Beispiel:

list.stream().map(data -> data.getSomeValue).map(this::getOptinalValue).flatMap(Optional::stream).collect(Collectors.toList());

  • Optional::stream benötigt java9

    – Avmohan

    3. Juli 2018 um 17:19 Uhr

  • Dieser Code ist a) länger als nur die Verwendung von if(opt.isPresent()) { val = opt.get());} und b) obskur und bedarf eines Kommentars, um dem nächsten Entwickler zu erklären, was Sie erreichen möchten und c) lässt sich nicht in Java 8 kompilieren.

    – Breandán Dalton

    8. Juni um 19:37 Uhr

  • Optional::stream benötigt java9

    – Avmohan

    3. Juli 2018 um 17:19 Uhr

  • Dieser Code ist a) länger als nur die Verwendung von if(opt.isPresent()) { val = opt.get());} und b) obskur und bedarf eines Kommentars, um dem nächsten Entwickler zu erklären, was Sie erreichen möchten und c) lässt sich nicht in Java 8 kompilieren.

    – Breandán Dalton

    8. Juni um 19:37 Uhr

1334200cookie-checkRichtige Verwendung von Optional.ifPresent()

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy