web-dev-qa-db-fra.com

Java contient le comportement vs anyMatch

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?

24
Tranquility

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.

24
Marco13

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.