Éléments communs dans deux listes


95

J'ai deux ArrayListobjets avec trois entiers chacun. Je veux trouver un moyen de renvoyer les éléments communs des deux listes. Quelqu'un at-il une idée de la façon dont je peux y parvenir?

Réponses:


161

Utilisez Collection#retainAll().

listA.retainAll(listB);
// listA now contains only the elements which are also contained in listB.

Si vous souhaitez éviter que les modifications ne soient affectées listA, vous devez en créer une nouvelle.

List<Integer> common = new ArrayList<Integer>(listA);
common.retainAll(listB);
// common now contains only the elements which are contained in listA and listB.

RetainAll renvoie une nouvelle liste? J'ai essayé de stocker la sortie de retenir dans une nouvelle liste sth comme celle-ci tempList.addAll (listA.retainAll (listB)); mais ça ne marche pas
zenitis

1
Comme répondu dans le lien ci-dessous Collection#retainAll()et les commentaires dans les extraits de code, non, ce n'est pas le cas. Les modifications sont reflétées dans la liste sur laquelle vous appelez la méthode.
BalusC

Le problème est que la liste commune est initialisée à la taille 3, alors vous essayez de changer sa taille en ne renvoyant qu'un ou deux éléments. J'essaye ce que vous suggérez et cela me renvoie une exception hors limites.
zenitis

Dans cette approche, je ne pourrai pas faire correspondre le numéro d'occurrence de l'élément ....... disons par exemple pour listA {2,3,5} et listB {5 5}, si je fais listB.retainAll (listA) , listB aura maintenant {5,5} ...... Je veux mon résultat final après avoir comparé listA et listB comme {5}. Veuillez suggérer comment nous pouvons y parvenir
NANCY

1
Si cela est fait avec un mauvais choix d'objet de collection, cela peut lever une exception UnsupportedOperationException. L'exemple ci-dessus avec ArrayList fonctionne bien sûr.
demongolem

39

Vous pouvez utiliser des opérations d'intersection définies avec vos ArrayListobjets.

Quelque chose comme ça:

List<Integer> l1 = new ArrayList<Integer>();

l1.add(1);
l1.add(2);
l1.add(3);

List<Integer> l2= new ArrayList<Integer>();
l2.add(4);
l2.add(2);
l2.add(3);

System.out.println("l1 == "+l1);
System.out.println("l2 == "+l2);

List<Integer> l3 = new ArrayList<Integer>(l2);
l3.retainAll(l1);

    System.out.println("l3 == "+l3);

Maintenant, l3ne devrait avoir que des éléments communs entre l1et l2.

CONSOLE OUTPUT
l1 == [1, 2, 3]
l2 == [4, 2, 3]
l3 == [2, 3]

6
Notez que de cette façon, les modifications sont également reflétées l2. Vous vouliez probablement dire à la List<Integer> l3 = new ArrayList<Integer>(l2);place.
BalusC

Le problème devient un peu plus compliqué si disons que l1 a 2 d'un élément et l2 a 3 de ce même élément. retientAll renvoie 3 de cet élément dans l3 même s'il n'est contenu que deux fois dans l1.
demongolem

35

Pourquoi réinventer la roue? Utilisez les collections communes :

CollectionUtils.intersection(java.util.Collection a, java.util.Collection b)

C'est une excellente solution, mais comme je l'ai mentionné ci-dessus, son comportement est différent de celui retainAll()des éléments répétés. Il est donc probable que l'un est correct et l'autre incorrect selon la façon dont vous abordez le problème.
demongolem

18

Utilisation de la Stream.filter()méthode de Java 8 en combinaison avec List.contains():

import static java.util.Arrays.asList;
import static java.util.stream.Collectors.toList;

/* ... */

List<Integer> list1 = asList(1, 2, 3, 4, 5);
List<Integer> list2 = asList(1, 3, 5, 7, 9);

List<Integer> common = list1.stream().filter(list2::contains).collect(toList());

4
Contains ressemble à une opération O (n), qui serait appelée n fois, à moins que le compilateur ne fasse quelque chose d'intelligent. Est-ce que quelqu'un sait si ce qui précède s'exécute en temps linéaire ou quadratique?
Regorsmitz

1
Ce serait une opération * n!
Lakshmikant Deshpande

5

entrez la description de l'image ici

            List<String> lista =new ArrayList<String>();
            List<String> listb =new ArrayList<String>();

            lista.add("Isabella");
            lista.add("Angelina");
            lista.add("Pille");
            lista.add("Hazem");

            listb.add("Isabella");
            listb.add("Angelina");
            listb.add("Bianca");

            // Create an aplusb list which will contain both list (list1 and list2) in which common element will occur twice 
            List<String> listapluslistb =new ArrayList<String>(lista);    
            listapluslistb.addAll(listb);

            // Create an aunionb set which will contain both list (list1 and list2) in which common element will occur once
            Set<String> listaunionlistb =new HashSet<String>(lista);
            listaunionlistb.addAll(listb);

            for(String s:listaunionlistb)
            {
                listapluslistb.remove(s);
            }
            System.out.println(listapluslistb);

Bien que ce code puisse répondre à la question, fournir un contexte supplémentaire sur la façon et / ou pourquoi il résout le problème améliorerait la valeur à long terme de la réponse.
Michael Parker

5
List<Integer> listA = new ArrayList<>();
    listA.add(1);
    listA.add(5);
    listA.add(3);
    listA.add(4);   

List<Integer> listB = new ArrayList<>();
    listB.add(1);
    listB.add(5);
    listB.add(6);
    listB.add(7);
System.out.println(listA.stream().filter(listB::contains).collect(Collectors.toList()));


Java 1.8 Stream API Solutions

Sortie [1, 5]


-Amélioration, nous pouvons définir la liste comme List <Integer> listA = asList (1, 5, 3, 4); List <Integer> listB = asList (1, 5, 6, 7);
Rajeev Ranjan

4

Vous pouvez obtenir les éléments communs entre deux listes en utilisant la méthode "retentionAll". Cette méthode supprimera tous les éléments sans correspondance de la liste à laquelle elle s'applique.

Ex.: list.retainAll(list1);

Dans ce cas de la liste, tous les éléments qui ne sont pas dans list1 seront supprimés et seuls resteront ceux qui sont communs entre list et list1.

List<Integer> list = new ArrayList<>();
list.add(10);
list.add(13);
list.add(12);
list.add(11);

List<Integer> list1 = new ArrayList<>();
list1.add(10);
list1.add(113);
list1.add(112);
list1.add(111);
//before retainAll
System.out.println(list);
System.out.println(list1);
//applying retainAll on list
list.retainAll(list1);
//After retainAll
System.out.println("list::"+list);
System.out.println("list1::"+list1);

Production:

[10, 13, 12, 11]
[10, 113, 112, 111]
list::[10]
list1::[10, 113, 112, 111]

REMARQUE: une fois la fonction RetainAll appliquée à la liste, la liste contient un élément commun entre list et list1.


4
public <T> List<T> getIntersectOfCollections(Collection<T> first, Collection<T> second) {
        return first.stream()
                .filter(second::contains)
                .collect(Collectors.toList());
    }

3
    // Create two collections:
    LinkedList<String> listA =  new LinkedList<String>();
    ArrayList<String> listB =  new ArrayList<String>();

    // Add some elements to listA:
    listA.add("A");
    listA.add("B");
    listA.add("C");
    listA.add("D");

    // Add some elements to listB:
    listB.add("A");
    listB.add("B");
    listB.add("C");

    // use 

    List<String> common = new ArrayList<String>(listA);
    // use common.retainAll

    common.retainAll(listB);

    System.out.println("The common collection is : " + common);

3

considérer deux listes L1 et L2

En utilisant Java8, nous pouvons facilement le trouver

L1.stream().filter(L2::contains).collect(Collectors.toList())


1

Au cas où vous voudriez le faire vous-même.

List<Integer> commons = new ArrayList<Integer>();

for (Integer igr : group1) {
    if (group2.contains(igr)) {
        commons.add(igr);
    }
}

System.out.println("Common elements are :: -");
for (Integer igr : commons) {
    System.out.println(" "+igr);
}

1
Le PO demandait un moyen de trouver les éléments communs et non le nombre d'éléments communs.
Brendon Dugan

@BrendonDugan - C'est ce que fait ce code. La liste commonscontient les éléments communs. La deuxième boucle for les imprime sur la console. Je ne vois pas où le code compte les éléments communs.
Ajoy Bhatia

@AjoyBhatia - Quand j'ai fait mon commentaire (en 2013), le code n'a renvoyé qu'un nombre d'éléments communs.
Brendon Dugan

@BrendonDugan Oh, d'accord. Désolé pour ça. Je dois garder à l'esprit que la réponse peut être modifiée sur place mais les commentaires sont généralement laissés tels
Ajoy Bhatia

0

Certaines des réponses ci-dessus sont similaires mais pas les mêmes, alors affichez-les comme une nouvelle réponse.

Solution:
1. Utilisez HashSet pour contenir les éléments qui doivent être supprimés
2. Ajoutez tous les éléments de list1 à HashSet
3. itérez list2 et supprimez les éléments d'un HashSet qui sont présents dans list2 ==> qui sont présents à la fois dans list1 et list2
4 . Maintenant, itérez sur HashSet et supprimez les éléments de list1 (puisque nous avons ajouté tous les éléments de list1 à set), enfin, list1 a tous les éléments communs
Note: Nous pouvons ajouter tous les éléments de list2 et dans une 3e itération, nous devrions supprimer des éléments de liste2.

Complexité temporelle: O (n)
Complexité spatiale: O (n)

Code:

import com.sun.tools.javac.util.Assert;
import org.apache.commons.collections4.CollectionUtils;

    List<Integer> list1 = new ArrayList<>();
    list1.add(1);
    list1.add(2);
    list1.add(3);
    list1.add(4);
    list1.add(5);

    List<Integer> list2 = new ArrayList<>();
    list2.add(1);
    list2.add(3);
    list2.add(5);
    list2.add(7);
    Set<Integer> toBeRemoveFromList1 = new HashSet<>(list1);
    System.out.println("list1:" + list1);
    System.out.println("list2:" + list2);
    for (Integer n : list2) {
        if (toBeRemoveFromList1.contains(n)) {
            toBeRemoveFromList1.remove(n);
        }
    }
    System.out.println("toBeRemoveFromList1:" + toBeRemoveFromList1);
    for (Integer n : toBeRemoveFromList1) {
        list1.remove(n);
    }
    System.out.println("list1:" + list1);
    System.out.println("collectionUtils:" + CollectionUtils.intersection(list1, list2));
    Assert.check(CollectionUtils.intersection(list1, list2).containsAll(list1));

production:

list1:[1, 2, 3, 4, 5]
list2:[1, 3, 5, 7]
toBeRemoveFromList1:[2, 4]
list1:[1, 3, 5]
collectionUtils:[1, 3, 5]
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.