Gemeinsame Elemente in zwei Listen


94

Ich habe zwei ArrayListObjekte mit jeweils drei ganzen Zahlen. Ich möchte einen Weg finden, die gemeinsamen Elemente der beiden Listen zurückzugeben. Hat jemand eine Idee, wie ich das erreichen kann?

Antworten:


158

Verwenden Sie Collection#retainAll().

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

Wenn Sie vermeiden möchten, dass Änderungen betroffen sind listA, müssen Sie eine neue erstellen.

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

RetainAll gibt eine neue Liste zurück? Ich habe versucht, die Ausgabe von keep in einer neuen Liste zu speichern, die etw tempList.addAll (listA.retainAll (listB)) enthält. aber es funktioniert nicht
Zenitis

1
Wie im Link dahinter Collection#retainAll()und in den Kommentaren in den Codefragmenten beantwortet , nein, das tut es nicht. Änderungen werden in der Liste angezeigt, für die Sie die Methode aufrufen.
BalusC

Das Problem ist, dass die allgemeine Liste mit Größe 3 initialisiert wird. Anschließend versuchen Sie, ihre Größe zu ändern, indem Sie nur ein oder zwei Elemente zurückgeben. Ich versuche, was Sie vorschlagen, und es gibt mir eine Ausnahme außerhalb der Grenzen zurück.
Zenitis

Bei diesem Ansatz kann ich die Vorkommensnummer des Elements nicht abgleichen ....... z. B. für listA {2,3,5} und listB {5 5}, wenn ich listB.retainAll (listA) ausführe. , listB hat jetzt {5,5} ...... Ich möchte mein endgültiges Ergebnis nach dem Vergleich von listA und listB als {5}. Bitte schlagen Sie vor, wie wir dies erreichen können
NANCY

1
Bei einer schlechten Auswahl des Auflistungsobjekts kann eine UnsupportedOperationException ausgelöst werden. Das obige Beispiel mit ArrayList funktioniert natürlich.
Demongolem

39

Sie können festgelegte Schnittoperationen mit Ihren ArrayListObjekten verwenden.

Etwas wie das:

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);

Nun l3sollte nur gemeinsame Elemente zwischen l1und haben l2.

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

6
Beachten Sie, dass sich auf diese Weise auch die Änderungen widerspiegeln l2. Sie wollten wahrscheinlich List<Integer> l3 = new ArrayList<Integer>(l2);stattdessen sagen .
BalusC

Das Problem wird etwas chaotischer, wenn sagen wir, l1 hat 2 eines Elements und l2 hat 3 desselben Elements. RetainAll gibt 3 dieses Elements in l3 zurück, obwohl es in l1 nur zweimal enthalten ist.
Demongolem

35

Warum das Rad neu erfinden? Verwendung Commons Kollektionen :

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

Dies ist eine großartige Lösung, die sich jedoch, wie oben erwähnt, anders verhält als retainAll()bei wiederholten Elementen. Je nachdem, wie Sie sich dem Problem nähern, ist wahrscheinlich einer richtig und einer falsch.
Demongolem

16

Verwendung der Java 8- Stream.filter()Methode in Kombination mit 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
Enthält sieht so aus, als wäre es eine O (n) -Operation, die n-mal aufgerufen würde, es sei denn, der Compiler macht etwas Kluges. Weiß jemand, ob das oben genannte in linearer oder quadratischer Zeit läuft?
Regorsmitz

1
Es wäre eine * n Operation!
Lakshmikant Deshpande

5

Geben Sie hier die Bildbeschreibung ein

            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);

Während dieser Code die Frage beantworten kann, würde die Bereitstellung eines zusätzlichen Kontexts darüber, wie und / oder warum er das Problem löst, den langfristigen Wert der Antwort verbessern.
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

Ausgabe [1, 5]


-Verbesserung wir können Liste als Liste <Integer> listA = asList (1, 5, 3, 4) definieren; List <Integer> listB = asList (1, 5, 6, 7);
Rajeev Ranjan

4

Sie können die gemeinsamen Elemente zwischen zwei Listen mit der Methode "keepAll" abrufen. Diese Methode entfernt alle nicht übereinstimmenden Elemente aus der Liste, für die sie gilt.

Ex.: list.retainAll(list1);

In diesem Fall werden aus der Liste alle Elemente entfernt, die nicht in Liste1 enthalten sind, und es bleiben nur die Elemente übrig, die zwischen Liste und Liste1 gemeinsam sind.

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);

Ausgabe:

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

HINWEIS: Nachdem keepAll auf die Liste angewendet wurde, enthält die Liste ein gemeinsames Element zwischen list und 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

Betrachten Sie zwei Listen L1 und L2

Mit Java8 können wir es leicht herausfinden

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


1

Für den Fall, dass Sie es selbst tun möchten ..

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
Das OP fragte nach einer Möglichkeit, herauszufinden, welche Elemente gemeinsam sind, nicht wie viele gemeinsame Elemente es gibt.
Brendon Dugan

@BrendonDugan - Genau das macht dieser Code. Die Liste commonsenthält die allgemeinen Elemente. Die zweite for-Schleife druckt sie auf der Konsole. Ich sehe nicht, wo der Code die gemeinsamen Elemente zählt.
Ajoy Bhatia

@AjoyBhatia - Als ich meinen Kommentar abgab (2013), gab der Code nur eine Anzahl gemeinsamer Elemente zurück.
Brendon Dugan

@BrendonDugan Oh, OK. Das tut mir leid. Ich sollte bedenken, dass die Antwort an Ort und Stelle bearbeitet werden kann, aber Kommentare werden normalerweise unverändert in chronologischer Reihenfolge belassen :-)
Ajoy Bhatia

0

Einige der obigen Antworten sind ähnlich, aber nicht identisch. Veröffentlichen Sie sie daher als neue Antwort.

Lösung:
1. Verwenden Sie HashSet, um Elemente zu speichern, die entfernt werden müssen.
2. Fügen Sie alle Elemente von list1 zu HashSet hinzu.
3. Iterieren Sie list2 und entfernen Sie Elemente aus einem HashSet, die in list2 ==> vorhanden sind und sowohl in list1 als auch in list2 vorhanden sind.
4 Iterieren Sie nun über HashSet und entfernen Sie Elemente aus Liste1 (da wir alle Elemente von Liste1 hinzugefügt haben, um sie festzulegen). Schließlich hat Liste1 alle gemeinsamen Elemente
Hinweis: Wir können alle Elemente von Liste2 hinzufügen und in einer dritten Iteration sollten wir Elemente aus Liste1 entfernen list2.

Zeitliche Komplexität: O (n)
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));

Ausgabe:

list1:[1, 2, 3, 4, 5]
list2:[1, 3, 5, 7]
toBeRemoveFromList1:[2, 4]
list1:[1, 3, 5]
collectionUtils:[1, 3, 5]
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.