Style fonctionnel de Java 8 est Facultatif.ifPresent et si n'est pas Présent?
Dans Java 8, je veux faire quelque chose à un Optional
objet, si elle est présente, et faire autre chose si elle n'est pas présente.
if (opt.isPresent()) {
System.out.println("found");
} else {
System.out.println("Not found");
}
Ce n'est pas un "style fonctionnel", bien.
Optional
a un ifPresent()
méthode, mais je suis incapable de chaîne d'une orElse()
méthode.
Donc, 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 Optional.map()
travaille 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, lorsque opt
est présent, je l'ai mise à jour de ses biens et de les enregistrer dans la base de données. Quand il n'est pas disponible, j'ai créer un nouveau obj
et de les enregistrer dans la base de données.
Remarque dans les deux lambdas j'ai du renvoyer null
.
Mais quand opt
est présent, les deux lambdas sera exécuté. obj
sera mis à jour, et un nouvel objet sera enregistré dans la base de données . C'est à cause de la return null
dans la première lambda. Et orElseGet()
continuera à exécuter.
orElse
est destiné à quelque chose de différent.- Oui , je sais . Je veux juste quelque chose comme ça.
- Utilisez votre premier échantillon. Il est beau.
- Je vous suggère d'arrêter de forcer certains comportements lors de l'utilisation d'une API qui n'est pas conçu pour que les comportements. Vous rfirst exemple semble bien pour moi en dehors de quelques petites style de commentaires, mais ceux-ci sont opiniated.
System.out.println( (opt.isPresent()? "" : "Not ") + "found");
- remplacer
return null;
avecreturn o;
(les deux). Cependant, j'ai le fort sentiment que vous travaillez à la mauvaise place. Vous devez travailler sur le site, qui a produit queOptional
. À cet endroit il y aurait lieu d'effectuer l'opération souhaitée sans l'intermédiaireOptional
. - Java 9 met en œuvre une solution à votre problème: iteratrlearning.com/java9/2016/09/05/java9-optional.html
- Je pense que la raison pour laquelle cela ne peut être fait facilement est sur le but. En option ne devrait pas faire de contrôle de flux, mais plutôt la transformation de la valeur. Je sais que le
ifPresent
contredit cela. Toutes les autres méthodes font référence à la valeur et non pas des actions. - Je dirais que votre deuxième exemple, qui utilise
map
, est encore moins fonctionnelle que laifPresent
version. En programmation fonctionnelle, les fonctions ne doit pas produire des effets secondaires tels que l'impression et la modification d'autres valeurs. Ils ne peuvent le faire les calculs. - Je éviter d'utilisermap
tout moment, je suis en train de produire des effets secondaires. En voyantmap
appelé, il est naturel de supposer qu'il n'y aura pas d'effets secondaires, seulement une transformation de la valeur, car il est fonctionnel arrière-plan. À l'aide de la manière que le suggère son nom, est une beaucoup plus de manière sémantique du programme. - Aussi, je ne suis pas sûr en Java, mais dans de nombreuses langues telles que la Rouille et Haskell,
map
est un paresseux opération en ce sens qu'elle ne sera pas réellement appeler le bloc que vous passer jusqu'à ce que vous essayez d'utiliser ou de vérifier la valeur de l'option. Donc, en fonction de la langue, une telle déclaration ne peut jamais être exécuté, et comme un résultat optimiser loin. Cela peut ne pas s'appliquer à Java, mais c'est quelque chose d'important à connaître.
Vous devez vous connecter pour publier un commentaire.
Pour moi, la réponse de @Dane Blanc est OK, d'abord, je n'aime pas utiliser l'Exécutable, mais je ne pouvais pas trouver toutes les solutions de rechange, voici une autre application que j'ai préféré plus
Alors :
Mise à jour 1:
la solution ci-dessus pour le mode traditionnel de développement quand vous avez de la valeur et à traiter, mais ce que si je veux définir la fonctionnalité et l'exécution sera ensuite, vérifiez ci-dessous d'amélioration;
Pourrait alors être utilisé comme:
Dans ce nouveau code, vous avez 3 choses:
par la façon dont aujourd'hui son nom est plus descriptive, il est effectivement Consommateur>
Si vous utilisez Java 9+, vous pouvez utiliser
ifPresentOrElse()
méthode:Voir excellent En option dans Java 8 feuille de triche.
Il fournit toutes les réponses pour la plupart des cas d'utilisation.
Bref résumé ci-dessous
ifPresent() - faire quelque chose lorsque l'Option est réglée
filtre() - rejet (à filtre) certaines valeurs Optionnelles.
map () de transformation de la valeur si elle est présente
orElse()/orElseGet() - tourner à vide en Option par défaut T
orElseThrow() - paresseusement lancer des exceptions à vide en Option
map
, mais il est un peu étrange de demander à une solution fonctionnelle de sorte que vous pouvez appeler un DAO. Me semble qu'il serait plus judicieux de revenir à la mise à jour/nouvel objet à partir de cettemap.orElse
bloc et ensuite faire ce que vous devez faire avec l'objet retourné.map
se concentrer sur le cours d'eau lui-même et n'est pas destiné à "faire les choses à un autre objet, selon le statut de cet élément dans le flux". Bon à savoir queifPresentOrElse
est ajoutée dans Java 9.Une alternative est la suivante:
Je ne pense pas que cela améliore la lisibilité bien.
Ou que Marko a suggéré, l'utilisation d'un opérateur ternaire:
new Object();
dans votre première lambda, mais pour être honnête, cela devient très laid. Je m'en tiendrais à un if/else pour la mise à jour de votre exemple.map
à juste retourOptional
pour le chaînage rend le code plus difficile à comprendre alors quemap
est supposé littéralement carte pour quelque chose.Une autre solution serait d'utiliser des fonctions d'ordre supérieur comme suit
value -> () -> syso
partie des moyens.String result = opt.map(value -> "withOptional").orElse("without optional");
Il n'y a pas une excellente façon de le faire hors de la boîte. Si vous souhaitez utiliser votre nettoyeur de syntaxe sur une base régulière, alors vous pouvez créer une classe utilitaire pour vous aider:
Ensuite, vous pouvez utiliser un statique à l'importation ailleurs pour obtenir la syntaxe est proche de ce que vous êtes après:
Optional.ifPresentOrElse()
a été ajouté à JDK 9.Si vous ne pouvez utiliser que Java 8 ou moins:
1) si vous n'avez pas
spring-data
le meilleur moyen à ce jour est:Maintenant, je sais que c'est pas si lisible et même difficile à comprendre pour quelqu'un, mais semble bien pour moi, personnellement, et je ne vois pas une autre belle couramment façon pour ce cas.
2) si vous êtes assez chanceux et vous pouvez utiliser
spring-data
la meilleure façon estOptions#ifPresentOrElse:
Si vous pouvez utiliser Java 9, vous devriez certainement aller avec:
Le comportement décrit peut être obtenue en utilisant Vavr (anciennement connu sous le Javaslang), un objet de la fonctionnelle de la bibliothèque de Java 8+, qui met en œuvre la plupart de la Scala de constructions (en cours de Scala plus expressif de la langue avec une manière plus riche type de système construit sur la JVM). C'est une très bonne bibliothèque à ajouter à vos projets Java pour écrire pure du code fonctionnel.
Vavr fournit la
Option
monade qui fournit des fonctions pour travailler avec le type d'Option comme:fold
: cartographier la valeur de l'option sur les deux cas (défini/vide)onEmpty
: permet d'exécuter unRunnable
lorsque l'option est videpeek
: permet de consommer la valeur de l'option (lorsqu'il est défini).Option suit la monade lois à la différence de Java, en Option, de "pseudo-monade" et fournit une plus riche de l'API. Et bien sûr, vous pouvez le faire à partir de Java, en Option, (et l'inverse):
Option.ofOptional(javaOptional)
–Vavr est axé sur l'interopérabilité.Va l'exemple:
Lecture
Référence nulle, les milliards de dollars d'erreur
N. B. Ce n'est qu'un tout petit exemple de ce que Vavr offre (correspondance, flux un.k.un. paresseux évalué listes, monadique types, immuable, collections,...).
Une autre solution pourrait être la suivante:
C'est la façon dont vous l'utiliser:
Ou dans le cas où vous dans le cas de la face de cas d'utilisation est vrai:
Ce sont les ingrédients:
La "cosmétiquement" Fonction améliorée de l'interface.
Et l'Option classe wrapper pour la mise en valeur:
Cela devrait faire l'affaire et pourrait servir de modèle de base, la façon de traiter avec de telles exigences.
L'idée de base ici est la suivante. Dans un non fonctionnel de style de programmation monde vous serait probablement mettre en œuvre une méthode prenant deux paramètres où le premier est une sorte de code exécutable qui doit être exécutée dans le cas où la valeur est disponible et l'autre paramètre est l'exécutable, code qui doit être exécuté dans le cas où la valeur n'est pas disponible. Pour des raisons de meilleure lisibilité, vous pouvez utiliser curring de scinder la fonction de deux paramètres dans deux fonctions d'un paramètre. C'est ce que je faisait ici.
Conseil: Opter fournit également les autres cas d'utilisation où vous voulez exécuter un morceau de code, juste au cas où la valeur n'est pas disponible. Cela peut être aussi fait via une Option.le filtre.des trucs, mais je trouve cela beaucoup plus lisible.
Espère que ça aide!
Bonne programmation 🙂
Dans le cas où vous souhaitez stocker la valeur:
En supposant que vous avez une liste et en évitant les isPresent() question (en rapport avec options) que vous pouvez utiliser .iterator().hasNext() pour vérifier si pas présent.