Donc, si j'ai un objet Name
et un ArrayList
de type Name
(names
), et que je veux vérifier si ma liste de noms contient un étant donné Name
objet (n
), je pourrais le faire de deux manières:
boolean exists = names.contains(n);
ou
boolean exists - names.stream().anyMatch(x -> x.equals(n));
Je me demandais si ces deux-là se comporteraient de la même manière, puis j'ai pensé à ce qui se passerait si n était assigné null
?
Pour contient, si je comprends bien, si l'argument est null
, alors il renvoie true
si la liste contient null
. Comment pourrais-je y parvenir anyMatch
- serait-ce en utilisant Objects.equals(x, n)
?
Si cela fonctionne, quelle approche est la plus efficace - est-ce anyMatch
car il peut tirer parti de la paresse et du parallélisme?
Le problème avec la version basée sur le flux est que si la collection (et donc son flux) contient des éléments null
, alors le prédicat lancera un NullPointerException
lorsqu'il essaiera pour appeler equals
sur cet objet null
.
Cela pourrait être évité avec
boolean exists = names.stream().anyMatch(x -> Objects.equals(x, n));
Mais il n'y a aucun avantage pratique à attendre pour la solution basée sur les flux dans ce cas. Le parallélisme peut apporter un avantage pour vraiment les grandes listes, mais il ne faut pas jeter par hasard quelques parallel()
ici et là en supposant qu'il peut accélérer les choses. Tout d'abord, vous devez clairement identifier les goulots d'étranglement réels.
Et en termes de lisibilité, je préférerais la première solution classique ici. Si vous voulez vérifier si la liste de names.contains(aParticularValue)
, vous devez le faire - elle se lit simplement comme de la prose et rend l'intention claire.
MODIFIER
Un autre avantage de l'approche contains
a été mentionné dans les commentaires et dans l'autre réponse, et cela peut être utile de le mentionner ici: si le type de la collection names
est modifié ultérieurement, par exemple, en être un HashSet
, alors vous obtiendrez le contains
- contrôle plus rapide (avec O(1) au lieu de O(n)) gratuitement - sans changer aucune autre partie du code. La solution basée sur le flux devrait alors encore parcourir tous les éléments , et cela pourrait avoir des performances nettement inférieures.
Ils devraient fournir le même résultat si hashCode()
et equals()
sont écrits de manière raisonnable.
Mais les performances peuvent être complètement différentes. Pour les listes, cela n'aurait pas beaucoup d'importance, mais pour HashSet contains()
utilisera hashCode()
pour localiser l'élément et cela se fera (très probablement) en temps constant. Tandis qu'avec la deuxième solution, elle fera une boucle sur tous les éléments et appellera une fonction, ce qui se fera en temps linéaire.
Si n est nul, cela n'a en fait pas d'importance car généralement les méthodes equals()
connaissent les arguments null
.