J'essaie de comprendre la méthode ifPresent()
de l'API Optional
dans Java 8.
J'ai une logique simple:
Optional<User> user=...
user.ifPresent(doSomethingWithUser(user.get()));
Mais cela entraîne une erreur de compilation:
ifPresent(Java.util.functionError:(186, 74) Java: 'void' type not allowed here)
Bien sûr, je peux faire quelque chose comme ça:
if(user.isPresent())
{
doSomethingWithUser(user.get());
}
Mais c’est exactement comme un contrôle null
encombré.
Si je change le code en ceci:
user.ifPresent(new Consumer<User>() {
@Override public void accept(User user) {
doSomethingWithUser(user.get());
}
});
Le code devient de plus en plus sale, ce qui me fait penser à revenir à l'ancien chèque null
.
Des idées?
Optional<User>.ifPresent()
prend un Consumer<? super User>
en argument. Vous lui transmettez une expression dont le type est vide. Donc, cela ne compile pas.
Un consommateur est destiné à être implémenté en tant qu'expression lambda:
Optional<User> user = ...
user.ifPresent(theUser -> doSomethingWithUser(theUser));
Ou encore plus simple, en utilisant une référence de méthode:
Optional<User> user = ...
user.ifPresent(this::doSomethingWithUser);
Ceci est fondamentalement la même chose que
Optional<User> user = ...
user.ifPresent(new Consumer<User>() {
@Override
public void accept(User theUser) {
doSomethingWithUser(theUser);
}
});
L'idée est que l'appel de la méthode doSomethingWithUser()
ne sera exécuté que si l'utilisateur est présent. Votre code exécute l'appel de méthode directement et tente de transmettre son résultat d'annulation à ifPresent()
.
Outre la réponse de @ JBNizet, mon cas d'utilisation général pour ifPresent consiste à combiner .isPresent()
et .get()
:
Ancienne façon:
Optional opt = getIntOptional();
if(opt.isPresent()) {
Integer value = opt.get();
// do something with value
}
Nouvelle façon:
Optional opt = getIntOptional();
opt.ifPresent(value -> {
// do something with value
})
Ceci, pour moi, est plus intuitif.
Utilisez flatMap. Si une valeur est présente, flatMap renvoie un flux séquentiel contenant uniquement cette valeur, sinon renvoie un flux vide. Il n’est donc pas nécessaire d’utiliser ifPresent()
. Exemple:
list.stream().map(data -> data.getSomeValue).map(this::getOptinalValue).flatMap(Optional::stream).collect(Collectors.toList());
Vous devez l'utiliser comme ceci:
user.ifPresent(ClassNameWhereMethodIs::doSomethingWithUser);
Méthode ifPresent()
obtient un objet Consumer
en tant que paramètre et (from JavaDoc ): "Si une valeur est présente, appelez le consommateur spécifié avec la valeur." Valeur c'est votre variable user
.
Pourquoi faire simple quand vous pouvez écrire du code compliqué!
En effet, si vous voulez absolument utiliser la classe Optional
, le code simple correspond à ce que vous avez déjà écrit ...
if (user.isPresent())
{
doSomethingWithUser(user.get());
}
Ce code présente les avantages d'être
Ce n'est pas parce que Oracle a ajouté la classe Optional
dans Java 8 que cette classe doit être utilisée dans toutes les situations.