Je veux vérifier si a List
contient un objet qui a un champ avec une certaine valeur. Maintenant, je pouvais utiliser une boucle pour parcourir et vérifier, mais j'étais curieux de savoir s'il y avait quelque chose de plus efficace.
Quelque chose comme;
if(list.contains(new Object().setName("John"))){
//Do some stuff
}
Je sais que le code ci-dessus ne fait rien, c'est juste pour montrer à peu près ce que j'essaie de réaliser.
Aussi, juste pour clarifier, la raison pour laquelle je ne veux pas utiliser une simple boucle est parce que ce code va actuellement à l'intérieur d'une boucle qui est à l'intérieur d'une boucle qui est à l'intérieur d'une boucle. Pour plus de lisibilité, je ne veux pas continuer à ajouter des boucles à ces boucles. Je me suis donc demandé s'il existait des alternatives simples (ish).
equals(Object)
méthode de votre objet personnalisé?for(Person p:list) if (p.getName().equals("John") return true; return false;
Vous ne trouverez pas un moyen plus concis en Java, je le crains.p.equals(p)
devrait toujours être vrai, donc je ne comprends pas ce que vous essayez de réaliser. J'espère que si vous posez une nouvelle question, vous pourrez obtenir une meilleure aide.Réponses:
Ruisseaux
Si vous utilisez Java 8, vous pouvez peut-être essayer quelque chose comme ceci:
Ou bien, vous pouvez essayer quelque chose comme ceci:
Cette méthode retournera
true
si leList<MyObject>
contient unMyObject
avec le nomname
. Si vous souhaitez effectuer une opération sur chacun desMyObject
s quegetName().equals(name)
vous pourriez essayer quelque chose comme ceci:Où
o
représente uneMyObject
instance.Alternativement, comme le suggèrent les commentaires (Merci MK10), vous pouvez utiliser la
Stream#anyMatch
méthode:la source
public boolean
. En outre, vous voudrez peut-être utiliserObjects.equals()
au cas où celao.getName()
pourrait l'êtrenull
.null
vérification, par opposition à une seule (la mienne).return list.stream().anyMatch(o -> o.getName().equals(name));
java.util.Objects
pour la comparaison nullsafereturn list.stream().anyMatch(o -> Objects.euqals(o.getName(), name);
Si vous voulez vérifier les objets dans le flux pour null, vous pouvez ajouter un.filter(Objects::nonNull)
avant anyMatch.Vous avez deux choix.
1. Le premier choix, qui est préférable, est de remplacer la méthode `equals ()` dans votre classe Object.
Disons, par exemple, que vous avez cette classe Object:
Supposons maintenant que vous vous souciez uniquement du nom de MyObject, qu'il doit être unique, donc si deux `MyObject`s ont le même nom, ils doivent être considérés comme égaux. Dans ce cas, vous voudrez remplacer la méthode `equals ()` (et aussi la méthode `hashcode ()`) afin qu'elle compare les noms pour déterminer l'égalité.
Une fois que vous avez fait cela, vous pouvez vérifier si une collection contient un MyObject avec le nom "foo" comme ceci:
Cependant, cela pourrait ne pas être une option pour vous si:
Si l'un ou l'autre est le cas, vous aurez besoin de l'option 2:
2. Écrivez votre propre méthode utilitaire:
Alternativement, vous pouvez étendre ArrayList (ou une autre collection), puis y ajouter votre propre méthode:
Malheureusement, il n'y a pas de meilleure solution.
la source
Google Guava
Si vous utilisez Guava , vous pouvez adopter une approche fonctionnelle et effectuer les opérations suivantes
qui a l'air un peu bavard. Cependant, le prédicat est un objet et vous pouvez fournir différentes variantes pour différentes recherches. Notez comment la bibliothèque elle-même sépare l'itération de la collection et la fonction que vous souhaitez appliquer. Vous n'avez pas à remplacer
equals()
un comportement particulier.Comme indiqué ci-dessous, le cadre java.util.Stream intégré à Java 8 et versions ultérieures fournit quelque chose de similaire.
la source
Iterables.any(list, predicate)
, qui est pratiquement le même, et vous pouvez ou non le préférer stylistiquement.Voici comment le faire en utilisant Java 8+:
la source
Collection.contains()
est implémenté en appelantequals()
chaque objet jusqu'à ce qu'un retournetrue
.Donc, une façon de l'implémenter est de remplacer,
equals()
mais bien sûr, vous ne pouvez avoir qu'un seul égal.Les cadres comme Guava utilisent donc des prédicats pour cela. Avec
Iterables.find(list, predicate)
, vous pouvez rechercher des champs arbitraires en plaçant le test dans le prédicat.D'autres langages construits au-dessus de la VM ont ceci intégré. Dans Groovy , par exemple, vous écrivez simplement:
Java 8 nous a aussi facilité la vie:
Si vous vous souciez de choses comme ça, je suggère le livre "Beyond Java". Il contient de nombreux exemples des nombreuses lacunes de Java et de la façon dont d'autres langages fonctionnent mieux.
la source
equals()
est très limitée. Cela signifie de vérifier "l'identité de l'objet" - quoi que cela puisse signifier pour une classe d'objets. Si vous ajoutez un indicateur indiquant les champs à inclure, cela peut provoquer toutes sortes de problèmes. Je le déconseille fortement.def result = list.find{ it.name == 'John' }
Oracle / JCP devrait être poursuivi pour crimes de guerre contre des programmeurs.Recherche binaire
Vous pouvez utiliser Collections.binarySearch pour rechercher un élément dans votre liste (en supposant que la liste est triée):
qui renverra un nombre négatif si l'objet n'est pas présent dans la collection ou bien il renverra le
index
de l'objet. Avec cela, vous pouvez rechercher des objets avec différentes stratégies de recherche.la source
Carte
Vous pouvez créer un en
Hashmap<String, Object>
utilisant l'une des valeurs comme clé, puis voir siyourHashMap.keySet().contains(yourValue)
renvoie true.la source
Collections Eclipse
Si vous utilisez des collections Eclipse , vous pouvez utiliser la
anySatisfy()
méthode. Soit adapter votreList
en aListAdapter
ou changer votreList
enListIterable
si possible.Si vous effectuez fréquemment des opérations comme celle-ci, il est préférable d'extraire une méthode qui indique si le type possède l'attribut.
Vous pouvez utiliser le formulaire alternatif
anySatisfyWith()
avec une référence de méthode.Si vous ne pouvez pas changer votre
List
en unListIterable
, voici comment vous l'utiliseriezListAdapter
.Remarque: je suis un committer pour les ollections Eclipse.
la source
Predicate
Si vous n'utilisez pas Java 8, ou une bibliothèque qui vous offre plus de fonctionnalités pour gérer les collections, vous pouvez implémenter quelque chose qui peut être plus réutilisable que votre solution.
j'utilise quelque chose comme ça, j'ai une interface de prédicat, et je passe l'implémentation à ma classe util.
Quel est l'avantage de faire cela à ma façon? vous avez une méthode qui traite de la recherche dans n'importe quelle collection de types. et vous n'avez pas à créer de méthodes distinctes si vous souhaitez effectuer une recherche par champ différent. tout ce que vous devez faire est de fournir un prédicat différent qui peut être détruit dès qu'il ne sert plus /
si vous voulez l'utiliser, il vous suffit d'appeler la méthode et de définir votre prédicat
la source
Voici une solution utilisant Guava
la source
contains
utilise enequals
interne. Vous devez donc remplacer leequals
méthode de votre classe selon vos besoins.Btw cela ne semble pas correct sur le plan statistique:
la source
this
.equals
pour un cas d'utilisation unique, sauf si cela a du sens pour la classe en général. Vous feriez mieux d’écrire la boucle.Si vous devez effectuer cette opération à
List.contains(Object with field value equal to x)
plusieurs reprises, une solution de contournement simple et efficace serait:Ensuite, le
List.contains(Object with field value equal to x)
serait le même résultat quefieldOfInterestValues.contains(x);
la source
vous pouvez également
anyMatch()
utiliser:la source
Malgré JAVA 8 SDK, de nombreuses bibliothèques d'outils de collecte peuvent vous aider à travailler, par exemple: http://commons.apache.org/proper/commons-collections/
la source