Elementy wspólne na dwóch listach


98

Mam dwa ArrayListobiekty z trzema liczbami całkowitymi każdy. Chcę znaleźć sposób na zwrócenie wspólnych elementów obu list. Czy ktoś ma pomysł, jak mogę to osiągnąć?

Odpowiedzi:


164

Użyj Collection#retainAll().

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

Jeśli chcesz uniknąć wpływu na zmiany w programie listA, musisz utworzyć nowy.

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

RetainAll zwraca nową listę? Próbowałem zapisać dane wyjściowe funkcji retain do nowej listy sth, takiej jak ta tempList.addAll (listA.retainAll (listB)); ale to nie działa
zenitis

1
Zgodnie z odpowiedzią w odnośniku za Collection#retainAll()i komentarzami we fragmentach kodu, nie, tak nie jest. Zmiany są odzwierciedlane na liście, na której wywołujesz metodę.
BalusC

Problem polega na tym, że lista common jest inicjalizowana z rozmiarem 3, a następnie próbujesz zmienić jej rozmiar, zwracając tylko jeden lub dwa elementy. Próbuję tego, co sugerujesz, i zwraca mi to wyjątek poza granice.
zenitis

W tym podejściu nie będę w stanie dopasować liczby wystąpień elementu… powiedzmy np. ListA {2,3,5} i listB {5 5}, jeśli zrobię listB.retainAll (listA) , listaB będzie teraz mieć {5,5} ...... Chcę uzyskać ostateczny wynik po porównaniu listA i listB jako {5}. Uprzejmie zasugeruj, jak możemy to osiągnąć
NANCY,

1
W przypadku złego wyboru obiektu kolekcji może to spowodować zgłoszenie wyjątku UnsupportedOperationException. Powyższy przykład z ArrayList oczywiście działa.
demongolem

39

Możesz użyć operacji ustawiania przecięcia z plikiem ArrayList obiektami.

Coś takiego:

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

Teraz l3powinny mieć tylko wspólne elementy między l1a l2.

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

6
Zauważ, że w ten sposób zmiany są również odzwierciedlane w l2. Prawdopodobnie chciałeś List<Integer> l3 = new ArrayList<Integer>(l2);zamiast tego powiedzieć .
BalusC

Problem staje się trochę bardziej skomplikowany, jeśli powiedzmy, że l1 ma 2 z elementu, a l2 ma 3 z tego samego elementu. retainAll return umieszcza 3 z tego elementu w l3, mimo że jest on zawarty tylko dwa razy w l1.
demongolem

35

Po co odkrywać koło na nowo? Użyj wspólnych zbiorów :

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

To świetne rozwiązanie, jednak jak wspomniałem powyżej, zachowuje się inaczej niż retainAll()na powtarzalnych elementach. Więc prawdopodobnie jeden jest poprawny, a drugi błędny, w zależności od tego, jak podejdziesz do problemu.
demongolem

18

Korzystanie z Stream.filter()metody Java 8 w połączeniu z 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
Zawiera wygląda na operację O (n), która byłaby wywoływana n razy, chyba że kompilator zrobi coś sprytnego. Czy ktoś wie, czy powyższe przebiega w czasie liniowym czy kwadratowym?
Regorsmitz,

1
To byłaby operacja * n!
Lakshmikant Deshpande

5

wprowadź opis obrazu tutaj

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

Chociaż ten kod może odpowiedzieć na pytanie, dostarczenie dodatkowego kontekstu dotyczącego tego, jak i / lub dlaczego rozwiązuje problem, poprawiłoby długoterminową wartość odpowiedzi.
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

Produkcja [1, 5]


-Improvementmożemy zdefiniować listę jako List <Integer> listA = asList (1, 5, 3, 4); Lista <Integer> listB = asList (1, 5, 6, 7);
Rajeev Ranjan

4

Możesz uzyskać wspólne elementy między dwiema listami za pomocą metody „retainAll”. Ta metoda usunie wszystkie niedopasowane elementy z listy, do której ma zastosowanie.

Ex.: list.retainAll(list1);

W tym przypadku z listy wszystkie elementy, których nie ma na liście 1, zostaną usunięte i pozostaną tylko te, które są wspólne między listą i listą1.

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

Wynik:

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

UWAGA: Po zastosowaniu retainAll na liście, lista zawiera wspólny element między list i list1.


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

4

rozważ dwie listy L1 i L2

Korzystając z Java8 możemy łatwo to sprawdzić

L1.stream().filter(L2::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);

1

Jeśli chcesz to zrobić sam ...

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
W PO pytano o sposób, aby ustalić, które elementy są wspólne, a nie ile jest ich wspólnych.
Brendon Dugan,

@BrendonDugan - To właśnie robi ten kod. Lista commonszawiera wspólne elementy. Druga pętla for drukuje je na konsoli. Nie widzę, gdzie kod liczy elementy wspólne.
Ajoy Bhatia

@AjoyBhatia - Kiedy skomentowałem (w 2013 r.), Kod zwrócił tylko liczbę wspólnych elementów.
Brendon Dugan

@BrendonDugan Och, OK. Przepraszam za to. Powinienem pamiętać, że odpowiedź można edytować na miejscu, ale komentarze są zwykle pozostawiane bez
zmian

0

Niektóre z powyższych odpowiedzi są podobne, ale nie takie same, więc zamieszczaj je jako nową odpowiedź.

Rozwiązanie:
1. Użyj HashSet do przechowywania elementów, które mają zostać usunięte
2. Dodaj wszystkie elementy listy1 do HashSet
3. iteruj list2 i usuń elementy z HashSet, które są obecne w list2 ==> które są obecne zarówno w list1, jak i list2
4 Teraz iteruj po HashSet i usuń elementy z listy1 (ponieważ dodaliśmy wszystkie elementy z listy1 do zestawu), w końcu lista1 ma wszystkie wspólne elementy
Uwaga: Możemy dodać wszystkie elementy listy2 iw trzeciej iteracji powinniśmy usunąć elementy z lista2.

Złożoność czasowa: O (n)
Złożoność przestrzeni: O (n)

Kod:

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

wynik:

list1:[1, 2, 3, 4, 5]
list2:[1, 3, 5, 7]
toBeRemoveFromList1:[2, 4]
list1:[1, 3, 5]
collectionUtils:[1, 3, 5]

0

Poniższy kod Usuń typowe elementy z listy

List<String> result =  list1.stream().filter(item-> !list2.contains(item)).collect(Collectors.toList());

Pobierz wspólne elementy

List<String> result = list1.stream()
                .distinct()
                .filter(list::contains)
                .collect(Collectors.toList());
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.