Elementi comuni in due elenchi


95

Ho due ArrayListoggetti con tre numeri interi ciascuno. Voglio trovare un modo per restituire gli elementi comuni dei due elenchi. Qualcuno ha idea di come posso ottenere questo risultato?

Risposte:


161

Usa Collection#retainAll().

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

Se si desidera evitare che le modifiche vengano modificate listA, è necessario crearne una nuova.

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

RetainAll restituisce un nuovo elenco? Ho provato a memorizzare l'output di Retain su una nuova lista sth come quella tempList.addAll (listA.retainAll (listB)); ma non funziona
zenitis

1
Come risposto nel link dietro Collection#retainAll()e nei commenti negli snippet di codice, no, non è così. Le modifiche si riflettono nell'elenco su cui stai chiamando il metodo.
BalusC

Il problema è che l'elenco comune viene inizializzato con la dimensione 3, quindi si tenta di modificarne la dimensione restituendo solo uno o due elementi. Provo quello che suggerisci e mi ritorna fuori limite l'eccezione.
zenitis

In questo approccio, non sarò in grado di abbinare il numero di occorrenze dell'elemento ....... diciamo ad esempio listA {2,3,5} e listB {5 5}, se farò listB.retainAll (listA) , listB ora avrà {5,5} ...... Voglio il mio risultato finale dopo aver confrontato listA e listB come {5}. Suggerire cortesemente come possiamo ottenere questo risultato
NANCY

1
Se eseguito con una scelta sbagliata dell'oggetto di raccolta, potrebbe generare un'eccezione UnsupportedOperationException. L'esempio sopra con ArrayList funziona ovviamente.
demongolem

39

È possibile utilizzare operazioni di intersezione impostate con i propri ArrayListoggetti.

Qualcosa come questo:

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

Ora, l3dovrebbe avere solo elementi comuni tra l1e l2.

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

6
Notare che in questo modo si riflettono anche le modifiche l2. Probabilmente volevi dire List<Integer> l3 = new ArrayList<Integer>(l2);invece.
BalusC

Il problema diventa un po 'più complicato se diciamo che l1 ha 2 di un elemento e l2 ha 3 dello stesso elemento. RetainAll restituisce 3 di quell'elemento in l3 anche se è contenuto solo due volte in l1.
demongolem

35

Perché reinventare la ruota? Usa le raccolte Commons :

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

Questa è un'ottima soluzione, tuttavia, come ho detto sopra, ha un comportamento diverso rispetto retainAll()agli elementi ripetuti. Quindi probabilmente uno è corretto e uno è sbagliato a seconda di come affronti il ​​problema.
demongolem

18

Utilizzando il Stream.filter()metodo di Java 8 in combinazione con 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
Contiene sembra che sarebbe un'operazione O (n), che verrebbe chiamata n volte, a meno che il compilatore non faccia qualcosa di intelligente. Qualcuno sa se quanto sopra viene eseguito in tempo lineare o quadratico?
Regorsmitz

1
Sarebbe un'operazione * n!
Lakshmikant Deshpande

5

inserisci qui la descrizione dell'immagine

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

Sebbene questo codice possa rispondere alla domanda, fornire un contesto aggiuntivo su come e / o perché risolve il problema migliorerebbe il valore a lungo termine della risposta.
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

Uscita [1, 5]


-Miglioramento possiamo definire lista come List <Integer> listA = asList (1, 5, 3, 4); List <Integer> listB = asList (1, 5, 6, 7);
Rajeev Ranjan

4

È possibile ottenere gli elementi comuni tra due elenchi utilizzando il metodo "keepAll". Questo metodo rimuoverà tutti gli elementi senza corrispondenza dall'elenco a cui si applica.

Ex.: list.retainAll(list1);

In questo caso dalla lista verranno rimossi tutti gli elementi non presenti in lista1 e rimarranno solo quelli comuni tra lista e lista1.

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

Produzione:

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

NOTA: dopo aver applicato keepAll all'elenco, l'elenco contiene l'elemento comune tra list e 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

considera due liste L1 e L2

Usando Java8 possiamo scoprirlo facilmente

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


1

Nel caso tu voglia farlo da solo ..

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
Il PO chiedeva un modo per scoprire quali elementi erano comuni, non quanti elementi comuni ci sono.
Brendon Dugan

@BrendonDugan - Questo è ciò che fa questo codice. L'elenco commonscontiene gli elementi comuni. Il secondo ciclo for li stampa sulla console. Non vedo dove il codice sta contando gli elementi comuni.
Ajoy Bhatia

@AjoyBhatia - Quando ho fatto il mio commento (nel 2013) il codice ha restituito solo un conteggio di elementi comuni.
Brendon Dugan

@BrendonDugan Oh, OK. Mi dispiace per quello. Devo tenere presente che la risposta può essere modificata sul posto ma i commenti di solito vengono lasciati così com'è, in ordine cronologico :-)
Ajoy Bhatia

0

Alcune delle risposte precedenti sono simili ma non uguali, quindi pubblicarle come una nuova risposta.

Soluzione:
1. Usa HashSet per contenere gli elementi che devono essere rimossi
2. Aggiungi tutti gli elementi di list1 a HashSet
3. itera list2 e rimuovi elementi da un HashSet che sono presenti in list2 ==> che sono presenti sia in list1 che in list2
4 . Ora itera su HashSet e rimuovi elementi da list1 (poiché abbiamo aggiunto tutti gli elementi di list1 a set), infine, list1 ha tutti gli elementi comuni
Nota: possiamo aggiungere tutti gli elementi di list2 e in una terza iterazione, dovremmo rimuovere elementi da list2.

Complessità temporale: O (n)
Complessità spaziale: O (n)

Codice:

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

produzione:

list1:[1, 2, 3, 4, 5]
list2:[1, 3, 5, 7]
toBeRemoveFromList1:[2, 4]
list1:[1, 3, 5]
collectionUtils:[1, 3, 5]
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.