J'essaie de comprendre la différence entre les méthodes Optional<T>.orElse()
et Optional<T>.orElseGet()
.
La description de la orElse()
méthode est "Renvoyer la valeur si présente, sinon renvoyer autre".
Tandis que la description de la orElseGet()
méthode est "Renvoyer la valeur si elle est présente, sinon invoquer autre et renvoyer le résultat de cette invocation".
La orElseGet()
méthode prend une interface fonctionnelle fournisseur, qui ne prend essentiellement aucun paramètre et retourne T
.
Dans quelle situation auriez-vous besoin d'utiliser orElseGet()
? Si vous avez une méthode, T myDefault()
pourquoi ne le feriez-vous pas optional.orElse(myDefault())
plutôt que optional.orElseGet(() -> myDefault())
?
Il ne semble pas que cela orElseGet()
retarde l'exécution de l'expression lambda à un moment ultérieur ou quelque chose comme ça, alors à quoi ça sert? (J'aurais pensé qu'il serait plus utile s'il renvoyait un coffre-fort Optional<T>
dont get()
jamais ne lance un NoSuchElementException
et isPresent()
renvoie toujours vrai ... mais évidemment ce n'est pas le cas, il revient juste T
comme orElse()
).
Y a-t-il une autre différence qui me manque?
orElseGet
il n'appelle le fournisseur que si la valeur est absente.orElse()
lamyDefault()
méthode est toujours appelée, mais sa valeur de retour n'est tout simplement pas utilisée.orElseGet()
peut entraîner de graves bugs: medium.com/alphadev-oughtts/…Réponses:
Prenez ces deux scénarios:
Si
opt
ne contient pas de valeur, les deux sont en effet équivalents. Mais siopt
ne contient une valeur, combienFoo
seront créés des objets?Ps: bien sûr, dans cet exemple, la différence ne serait probablement pas mesurable, mais si vous devez obtenir votre valeur par défaut à partir d'un service Web distant par exemple, ou d'une base de données, cela devient soudain très important.
la source
Foo
objet, tandis que dans le premier cas il le créera, mais ne l'utilisera pas s'il y a une valeur à l'intérieur deOptional
.System.out.println()
n'est pas un calcul mais une déclaration produisant un effet secondaire observable. Et j'ai déjà dit que les effets secondaires observables entraveraient les optimisations (le flux de sortie de la console est une ressource externe).Réponse courte:
Optional.isPresent()
valeurOptional.isPresent() == false
Dans le code réel, vous voudrez peut-être envisager la deuxième approche lorsque la ressource requise est coûteuse à obtenir .
Pour plus de détails, considérez l'exemple suivant avec cette fonction:
La différence est comme ci-dessous:
Quand
optional.isPresent() == false
, il n'y a pas de différence entre deux façons. Cependant, lorsqueoptional.isPresent() == true
,orElse()
appelle toujours la fonction suivante, que vous le vouliez ou non.Enfin, le cas de test utilisé est le suivant:
Résultat:
Code:
la source
Optional.isPresent() == false
place (faux, pas vrai)Optional.orElse
lesquels les étatsIf a value is present, returns the value, otherwise returns other
peuvent impliquer ce comportement ...orElse()
comportement similaire à celuifinally
de l'try-catch
expression. Ai-je raison?Je suis arrivé ici pour le problème mentionné par Kudo .
Je partage mon expérience pour les autres.
orElse
, ouorElseGet
, telle est la question:impressions
orElse
évalue la valeur de B () de manière interdépendante de la valeur de l'option. Ainsi,orElseGet
est paresseux.la source
B()
à une méthode nomméeorElse()
ou queabc()
cela ne fait aucune différence,B()
est évalué.or
préfixe induit les développeurs (y compris moi-même lorsque j'ai posé la question) en pensant qu'il s'agit d'une opération de court-circuit, car c'est ce à quoi nous sommes habitués dans des conditions booléennes. Cependant, ce n'est pas le cas, c'est juste un nom de méthode qui aor
dans son préfixe, donc ses arguments seront évalués, qu'ilOptional
porte ou non une valeur. Il est regrettable que la dénomination soit source de confusion, pas que nous puissions y faire quoi que ce soit.Je dirais que la plus grande différence entre
orElse
etorElseGet
vient lorsque nous voulons évaluer quelque chose pour obtenir la nouvelle valeur dans laelse
condition.Considérez cet exemple simple -
Transformons maintenant l'exemple ci-dessus en utilisant
Optional
avecorElse
,Transformons maintenant l'exemple ci-dessus en utilisant
Optional
avecorElseGet
,Lorsque
orElse
est invoqué, leapicall().value
est évalué et transmis à la méthode. Alors que, dans le cas deorElseGet
l'évaluation, il ne se produit que si leoldValue
est vide.orElseGet
permet une évaluation paresseuse.la source
L'exemple suivant doit démontrer la différence:
La réponse apparaît également dans les documents.
public T orElseGet(Supplier<? extends T> other)
:Le
Supplier
ne sera pas invoqué si lesOptional
cadeaux. tandis que,public T orElse(T other)
:Si
other
est une méthode qui renvoie une chaîne, elle sera invoquée, mais sa valeur ne sera pas retournée au cas où elleOptional
existe.la source
La différence est assez subtile et si vous n'y prêtez pas beaucoup attention, vous continuerez à l'utiliser de manière incorrecte.
La meilleure façon de comprendre la différence entre
orElse()
etorElseGet()
est qu'elleorElse()
sera toujours exécutée si la valeurOptional<T>
est nulle ou non , maisorElseGet()
ne sera exécutée que lorsque la valeurOptional<T>
est nulle .La signification du dictionnaire de orElse est : - exécutez la partie quand quelque chose n'est pas présent, mais ici cela contredit, voir l'exemple ci-dessous:
Repères :
J'espère que cela efface les doutes de personnes comme moi qui veulent l'exemple fondamental de base :)
la source
Vérifiez tout d'abord la déclaration des deux méthodes.
1) OrElse: exécuter la logique et passer le résultat en argument.
2) OrElseGet: Exécute la logique si la valeur à l'intérieur de l'option est nulle
Quelques explications sur la déclaration ci-dessus: L'argument de "Optional.orElse" est toujours exécuté quelle que soit la valeur de l'objet en option (null, vide ou avec valeur). Tenez toujours compte du point mentionné ci-dessus lorsque vous utilisez «Optional.orElse», sinon l'utilisation de «Optional.orElse» peut être très risquée dans la situation suivante.
Risque-1) Problème de journalisation: si le contenu dans orElse contient une instruction de journal: dans ce cas, vous finirez par le journaliser à chaque fois.
Risque-2) Problème de performances: si le contenu dans orElse est chronophage : le contenu chronophage peut être n'importe quel appel de base de données d'opérations d'E / S, appel d'API, lecture de fichier. Si nous mettons un tel contenu dans orElse (), le système finira par exécuter un code inutile.
Risque-3) Problème d'état ou de bogue illégal: Si le contenu dans orElse mute un état d'objet: nous pourrions utiliser le même objet à un autre endroit, disons à l'intérieur de la fonction Optional.map et cela peut nous mettre dans un bogue critique.
Alors, quand peut-on aller avec orElse ()? Préférez utiliser orElse lorsque la valeur par défaut est un objet constant, enum. Dans tous les cas ci-dessus, nous pouvons utiliser Optional.orElseGet () (qui ne s'exécute que lorsque Optional contient une valeur non vide) au lieu de Optional.orElse (). Pourquoi?? Dans orElse, nous transmettons la valeur de résultat par défaut, mais dans orElseGet, nous transmettons Supplier et la méthode de Supplier ne s'exécute que si la valeur dans Optional est nulle.
Points clés à retenir de ceci:
Je l'ai expliqué au point-2 ( "Optional.map/Optional.orElse"! = "If / else" ) mon blog moyen. Utiliser Java8 comme programmeur et non comme codeur
la source
Considérant le code suivant:
si nous obtenons
value
de cette façon:Optional.<String>ofNullable(null)
, il n'y a pas de différence entre orElseGet () et OrElse (), mais si nous obtenonsvalue
de cette façon:Optional.<String>ofNullable("test")
,orelesMethod()
enorElseGet()
ne sera pas appelé maisorElse()
il sera appeléla source