web-dev-qa-db-fra.com

Vérifier si une liste contient un élément de l'autre

J'ai deux listes avec différents objets en eux.

List<Object1> list1;
List<Object2> list2;

Je veux vérifier si un élément de list1 existe dans list2, basé sur un attribut spécifique (Object1 et Object2 ont (entre autres), un attribut mutuel (de type Long), nommé attributeSame).

maintenant, je le fais comme ça:

boolean found = false;
for(Object1 object1 : list1){
   for(Object2 object2: list2){
       if(object1.getAttributeSame() == object2.getAttributeSame()){
           found = true;
           //also do something
       }
    }
    if(!found){
        //do something
    }
    found = false;
}

Mais je pense qu’il existe un moyen plus rapide et meilleur de le faire :) Quelqu'un peut-il le proposer?

Merci!

91
Ned

Si vous avez juste besoin de tester l’égalité de base, vous pouvez le faire avec le JDK de base sans modifier les listes d’entrée sur une ligne.

!Collections.disjoint(list1, list2);

Si vous avez besoin de tester une propriété spécifique, c'est plus difficile. Je recommanderais, par défaut,

list1.stream()
   .map(Object1::getProperty)
   .anyMatch(
     list2.stream()
       .map(Object2::getProperty)
       .collect(toSet())
       ::contains)

... qui rassemble les valeurs distinctes dans list2 et teste chaque valeur dans list1 pour la présence.

200
Louis Wasserman

Vous pouvez utiliser Apache Commons CollectionUtils :

if(CollectionUtils.containsAny(list1,list2)) {  
    // do whatever you want
} else { 
    // do other thing 
}  

Cela suppose que vous avez correctement surchargé la fonctionnalité égal à vos objets personnalisés.

35
Woot4Moo

Il y a une méthode de Collection nommée retainAll mais ayant certains effets secondaires pour vous référence

Conserve uniquement les éléments de cette liste contenus dans la collection spécifiée (opération facultative). En d'autres termes, supprime de cette liste tous les éléments qui ne sont pas contenus dans la collection spécifiée.

true si cette liste a changé à la suite de l'appel

C'est comme

boolean b = list1.retainAll(list2);
9
Harmeet Singh

Louis répond est correct, je veux juste ajouter un exemple:

listOne.add("A");
listOne.add("B");
listOne.add("C");

listTwo.add("D");
listTwo.add("E");
listTwo.add("F");      

boolean noElementsInCommon = Collections.disjoint(listOne, listTwo); // true
5
Matias Elorriaga

Pour raccourcir la logique de Narendra, vous pouvez utiliser ceci:

boolean var = lis1.stream().anyMatch(element -> list2.contains(element));
3
ketanjain

manière plus rapide nécessitera un espace supplémentaire.

Par exemple:

  1. mettre tous les éléments d'une liste dans un hachage (vous devez implémenter vous-même la fonction de hachage pour utiliser object.getAttributeSame ())

  2. Parcourez l'autre liste et vérifiez si un élément est présent dans le HashSet.

De cette façon, chaque objet est visité au plus une fois. et HashSet est assez rapide pour vérifier ou insérer un objet dans O (1).

2
lavin

pour le rendre plus rapide, vous pouvez ajouter une pause; de cette façon, la boucle s’arrêtera si elle est trouvée à true:

boolean found = false;
for(Object1 object1 : list1){
   for(Object2 object2: list2){
       if(object1.getAttributeSame() == object2.getAttributeSame()){
           found = true;
           //also do something  
           break;
       }
    }
    if(!found){
        //do something
    }
    found = false;
}

Si vous aviez des cartes au lieu de listes avec comme clés l'attributSame, vous pourriez vérifier plus rapidement si une valeur d'une carte correspond à une valeur correspondante ou non.

2
Tom

Selon le JavaDoc pour le .contains(Object obj) :

Renvoie true si cette liste contient l'élément spécifié. Plus formellement, renvoie vrai si et seulement si cette liste contient au moins un élément e tel que (o == null? E == null: o.equals (e)).

Donc, si vous substituez votre méthode .equals() à votre objet donné, vous devriez pouvoir faire: if(list1.contains(object2))...

Si les éléments sont uniques (c.-à-d. Qu'ils ont des attributs différents), vous pouvez remplacer les .equals() et .hashcode() et tout stocker dans HashSets . Cela vous permettra de vérifier si l'un contient un autre élément en temps constant.

2
npinti

org.springframework.util.CollectionUtils

boolean containsAny(Java.util.Collection<?> source, Java.util.Collection<?> candidates)

Return true if any element in 'candidates' is contained in 'source'; otherwise returns false
0
akjain

Avec Java 8, on peut faire comme ci-dessous pour vérifier si une liste contient un élément d’un autre

boolean var = lis1.stream().filter(element -> list2.contains(element)).findFirst().isPresent();
0
Narendra Jaggi

Pouvez-vous définir le type de données que vous détenez? est-ce le big data? est-ce trié? Je pense que vous devez envisager différentes approches d'efficacité en fonction des données.

Par exemple, si vos données sont volumineuses et non triées, vous pouvez essayer de parcourir les deux listes ensemble par index et de stocker chaque attribut de liste dans un autre assistant de liste. vous pouvez ensuite vérifier par les attributs actuels dans les listes d’aides.

bonne chance

édité: et je ne recommanderais pas de surcharger égaux. son dangereux et probablement contre votre objet oop sens.

0
R-E-L