En Java 8, je veux faire quelque chose à un Optional
objet s'il est présent, et faire autre chose s'il n'est pas présent.
if (opt.isPresent()) {
System.out.println("found");
} else {
System.out.println("Not found");
}
Ce n'est cependant pas un «style fonctionnel».
Optional
a une ifPresent()
méthode, mais je ne peux pas enchaîner une orElse()
méthode.
Ainsi, je ne peux pas écrire:
opt.ifPresent( x -> System.out.println("found " + x))
.orElse( System.out.println("NOT FOUND"));
En réponse à @assylias, je ne pense pas que cela Optional.map()
fonctionne pour le cas suivant:
opt.map( o -> {
System.out.println("while opt is present...");
o.setProperty(xxx);
dao.update(o);
return null;
}).orElseGet( () -> {
System.out.println("create new obj");
dao.save(new obj);
return null;
});
Dans ce cas, lorsqu'il opt
est présent, je mets à jour sa propriété et l'enregistre dans la base de données. Lorsqu'il n'est pas disponible, j'en crée un nouveau obj
et l'enregistre dans la base de données.
Remarque dans les deux lambdas je dois revenir null
.
Mais quand il opt
est présent, les deux lambdas seront exécutés. obj
sera mis à jour et un nouvel objet sera enregistré dans la base de données. C'est à cause de return null
la première lambda. Et orElseGet()
continuera à exécuter.
la source
return null;
parreturn o;
(les deux). Cependant, j'ai le fort sentiment que vous travaillez au mauvais endroit. Vous devriez travailler sur le site qui a produit celaOptional
. À cet endroit, il devrait y avoir un moyen d'effectuer l'opération souhaitée sans l'intermédiaireOptional
.ifPresent
cela contredit. Toutes les autres méthodes font référence à la valeur et non aux actions.Réponses:
Pour moi, la réponse de @Dane White est OK, d'abord je n'ai pas aimé utiliser Runnable mais je n'ai trouvé aucune alternative, ici une autre implémentation que j'ai préféré plus
Ensuite :
Mise à jour 1:
la solution ci-dessus pour le mode de développement traditionnel lorsque vous avez la valeur et que vous souhaitez la traiter mais que se passe-t-il si je veux définir la fonctionnalité et l'exécution sera alors, vérifiez l'amélioration ci-dessous;
Ensuite, pourrait être utilisé comme:
Dans ce nouveau code, vous avez 3 choses:
à propos maintenant son nom est plus descriptif, il est en fait consommateur>
la source
Si vous utilisez Java 9+, vous pouvez utiliser la
ifPresentOrElse()
méthode:la source
Java 9 présente
ifPresentOrElse si une valeur est présente, exécute l'action donnée avec la valeur, sinon exécute l'action basée sur le vide donnée.
Voir excellente feuille de triche facultative dans Java 8 .
Il fournit toutes les réponses pour la plupart des cas d'utilisation.
Bref résumé ci-dessous
ifPresent () - faire quelque chose lorsque Facultatif est défini
filter () - rejeter (filtrer) certaines valeurs facultatives.
map () - transforme la valeur si elle est présente
orElse () / orElseGet () - tourner vide Facultatif à T par défaut
orElseThrow () - levée paresseuse des exceptions sur vide Facultatif
la source
map
, mais c'est un peu étrange de demander une solution fonctionnelle pour que vous puissiez appeler un DAO. Il me semble qu'il serait plus judicieux de renvoyer l'objet mis à jour / nouveau à partir de cemap.orElse
bloc, puis de faire ce que vous devez faire avec l'objet renvoyé.map
concentrer sur le flux lui-même et n'est pas destiné à "faire des choses à un autre objet en fonction du statut de cet élément dans le flux". Bon à savoir quiifPresentOrElse
est ajouté dans Java 9.Une alternative est:
Je ne pense pas que cela améliore la lisibilité.
Ou comme l'a suggéré Marko, utilisez un opérateur ternaire:
la source
new Object();
dans votre premier lambda mais pour être honnête cela devient très moche. Je m'en tiendrai à un if / else pour votre exemple mis à jour.map
de simplement revenirOptional
pour le chaînage rend le code plus difficile à comprendre alors que l'map
on suppose qu'il correspond littéralement à quelque chose.Une autre solution serait d'utiliser des fonctions d'ordre supérieur comme suit
la source
value -> () -> syso
signifie la partie.String result = opt.map(value -> "withOptional").orElse("without optional");
Il n'y a pas un excellent moyen de le faire hors de la boîte. Si vous souhaitez utiliser régulièrement votre syntaxe de nettoyage, vous pouvez créer une classe utilitaire pour vous aider:
Ensuite, vous pouvez utiliser une importation statique ailleurs pour obtenir une syntaxe proche de ce que vous recherchez:
la source
Optional.ifPresentOrElse()
a été ajouté au JDK 9.Si vous ne pouvez utiliser que Java 8 ou une version antérieure:
1) si vous ne disposez pas
spring-data
du meilleur moyen jusqu'à présent:Maintenant, je sais que ce n'est pas si lisible et même difficile à comprendre pour quelqu'un, mais ça me va bien personnellement et je ne vois pas une autre belle manière fluide pour ce cas.
2) si vous êtes assez chanceux et que vous pouvez utiliser
spring-data
le meilleur moyen est Optionals # ifPresentOrElse :Si vous pouvez utiliser Java 9, vous devez absolument utiliser:
la source
Le comportement décrit peut être obtenu en utilisant Vavr (anciennement Javaslang), une bibliothèque fonctionnelle pour Java 8+, qui implémente la plupart des constructions Scala (Scala étant un langage plus expressif avec un système de type beaucoup plus riche basé sur JVM). C'est une très bonne bibliothèque à ajouter à vos projets Java pour écrire du code fonctionnel pur.
Vavr fournit la
Option
monade qui fournit des fonctions pour travailler avec le type d'option telles que:fold
: pour mapper la valeur de l'option sur les deux cas (défini / vide)onEmpty
: permet d'exécuter uneRunnable
option quand est videpeek
: permet de consommer la valeur de l'option (lorsqu'elle est définie).Serializable
au contraireOptional
ce qui signifie que vous pouvez l'utiliser en toute sécurité comme argument de méthode et membre d'instance.L'option suit les lois de la monade à la différence de la "pseudo-monade" facultative de Java et fournit une API plus riche. Et bien sûr, vous pouvez le faire à partir d'un Java facultatif (et
Option.ofOptional(javaOptional)
inversement ): –Vavr se concentre sur l'interopérabilité.En passant à l'exemple:
Lectures complémentaires
Référence nulle, l'erreur d'un milliard de dollars
NB Ce n'est qu'un très petit exemple de ce que propose Vavr (correspondance de modèles, streams ou listes évaluées paresseuses, types monadiques, collections immuables, ...).
la source
Une autre solution pourrait être la suivante:
Voici comment vous l'utilisez:
Ou dans le cas où vous dans le cas d'utilisation contraire est vrai:
Ce sont les ingrédients:
L'interface de fonction améliorée "cosmétiquement".
Et la classe wrapper facultatif pour l'amélioration:
Cela devrait faire l'affaire et pourrait servir de modèle de base pour gérer ces exigences.
L'idée de base ici est la suivante. Dans un monde de programmation de style non fonctionnel, vous implémenteriez probablement une méthode prenant deux paramètres où le premier est une sorte de code exécutable qui devrait être exécuté au cas où la valeur est disponible et l'autre paramètre est le code exécutable qui devrait être exécuté au cas où le la valeur n'est pas disponible. Dans un souci de meilleure lisibilité, vous pouvez utiliser le récurage pour diviser la fonction de deux paramètres en deux fonctions d'un paramètre chacune. C'est ce que j'ai essentiellement fait ici.
Astuce: Opt fournit également l'autre cas d'utilisation où vous souhaitez exécuter un morceau de code au cas où la valeur ne serait pas disponible. Cela pourrait être fait également via Optional.filter.stuff mais j'ai trouvé cela beaucoup plus lisible.
J'espère que cela pourra aider!
Bonne programmation :-)
la source
Si vous souhaitez stocker la valeur:
la source
Supposons que vous ayez une liste et évitez le
isPresent()
problème (lié aux options) que vous pourriez utiliser.iterator().hasNext()
pour vérifier s'il n'est pas présent.la source