it-swarm.com.de

Ordnungsgemäße Verwendung von Optional.ifPresent ()

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

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());
}

Dies ist jedoch genau wie ein überladener null-Check.

Wenn ich den Code in dieses ändern:

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

Der Code wird schmutziger, was mich an den alten null-Check denken lässt.

Irgendwelche Ideen?

55
rayman

Optional<User>.ifPresent() nimmt einen Consumer<? super User> als Argument an. Sie übergeben einen Ausdruck, dessen Typ leer ist. Das wird also nicht kompiliert. 

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 der Aufruf der doSomethingWithUser()-Methode nur ausgeführt wird, wenn der Benutzer anwesend ist. Ihr Code führt den Methodenaufruf direkt aus und versucht, das ungültige Ergebnis an ifPresent() zu übergeben.

96
JB Nizet

Neben der Antwort von @ JBNizet besteht mein allgemeiner Anwendungsfall für ifPresent darin, .isPresent() und .get() zu kombinieren:

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.

8
cst1992

FlatMap verwenden. Wenn ein Wert vorhanden ist, gibt flatMap einen sequentiellen Stream zurück, der nur diesen Wert enthält. Andernfalls wird ein leerer Stream zurückgegeben. Es ist also nicht nötig, ifPresent() zu verwenden. Beispiel:

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

Sie müssen es so verwenden:

user.ifPresent(ClassNameWhereMethodIs::doSomethingWithUser);

Methode ifPresent() get Consumer object als Parameter und (aus JavaDoc ): "Wenn ein Wert vorhanden ist, rufen Sie den angegebenen Consumer mit dem Wert auf." Wert ist deine Variable user.

3

Warum einfach machen, wenn Sie komplizierten Code schreiben können!

Wenn Sie unbedingt die Klasse Optional verwenden, ist der einfache Code der, den Sie bereits geschrieben haben ...

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

Dieser Code hat die Vorteile zu sein 

  1. lesbar 
  2. leicht zu knacken 
  3. nicht knifflig

Es ist nicht so, dass Oracle in Java 8 eine Optional-Klasse hinzugefügt hat, die diese Klasse in allen Situationen verwenden muss.

1
schlebe