Elemen umum dalam dua daftar


95

Saya memiliki dua ArrayListobjek dengan masing-masing tiga bilangan bulat. Saya ingin menemukan cara untuk mengembalikan elemen umum dari dua daftar. Adakah yang punya ide bagaimana saya bisa mencapai ini?

Jawaban:


161

Gunakan Collection#retainAll().

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

Jika Anda ingin menghindari perubahan yang terpengaruh listA, Anda perlu membuat yang baru.

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

RetainAll mengembalikan daftar baru? Saya mencoba untuk menyimpan output dari mempertahankan ke daftar baru sth seperti itu tempList.addAll (listA.retainAll (listB)); tetapi tidak berhasil
zenitis

1
Seperti yang dijawab di tautan di belakang Collection#retainAll()dan komentar di cuplikan kode, tidak, tidak. Perubahan tercermin dalam daftar tempat Anda memanggil metode ini.
BalusC

Masalahnya list common itu diinisialisasi dengan ukuran 3, lalu coba ubah ukurannya dengan mengembalikan hanya satu atau dua elemen. Saya mencoba apa yang Anda sarankan dan itu mengembalikan saya di luar batas pengecualian.
zenitis

Dalam pendekatan ini, saya tidak akan dapat mencocokkan jumlah kemunculan elemen ....... katakan untuk misalnya listA {2,3,5} dan listB {5 5}, jika saya akan melakukan listB.retainAll (listA) , listB sekarang akan memiliki {5,5} ...... Saya ingin hasil akhir saya setelah membandingkan listA dan listB sebagai {5}. Mohon sarankan bagaimana kami dapat mencapai ini
NANCY

1
Jika dilakukan dengan pilihan objek koleksi yang buruk, itu bisa memunculkan UnsupportedOperationException. Contoh di atas dengan ArrayList tentu saja berfungsi.
demongolem

39

Anda dapat menggunakan operasi persimpangan set dengan ArrayListobjek Anda .

Sesuatu seperti ini:

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

Sekarang, l3seharusnya hanya memiliki elemen yang sama antara l1dan l2.

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

6
Perhatikan bahwa dengan cara ini perubahan juga tercermin l2. Anda mungkin bermaksud mengatakannya List<Integer> l3 = new ArrayList<Integer>(l2);.
BalusC

Masalah menjadi sedikit lebih berantakan jika l1 memiliki 2 elemen dan l2 memiliki 3 elemen yang sama. ReturAll return menempatkan 3 dari elemen itu di l3 meskipun itu hanya dimuat dua kali di l1.
demongolem

35

Mengapa menemukan kembali roda? Gunakan Koleksi Commons :

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

Ini adalah solusi yang bagus, namun seperti yang saya sebutkan di atas, ini memiliki perilaku yang berbeda dari retainAll()pada elemen berulang. Jadi kemungkinan besar salah satu benar dan satu tidak benar tergantung pada bagaimana Anda mendekati masalah.
demongolem

18

Menggunakan Stream.filter()metode Java 8 yang dikombinasikan dengan 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
Berisi sepertinya itu akan menjadi operasi O (n), yang akan dipanggil n kali, kecuali kompiler melakukan sesuatu yang pintar. Adakah yang tahu apakah hal di atas berjalan dalam waktu linier atau kuadrat?
Regorsmitz

1
Ini akan menjadi operasi * n!
Lakshmikant Deshpande

5

masukkan deskripsi gambar di sini

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

Meskipun kode ini dapat menjawab pertanyaan, memberikan konteks tambahan tentang bagaimana dan / atau mengapa kode ini memecahkan masalah akan meningkatkan nilai jawaban jangka panjang.
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

Keluaran [1, 5]


-Improvementwe dapat mendefinisikan daftar sebagai List <Integer> listA = asList (1, 5, 3, 4); Daftar <Integer> listB = asList (1, 5, 6, 7);
Rajeev Ranjan

4

Anda bisa mendapatkan elemen umum di antara dua daftar menggunakan metode "retretAll". Metode ini akan menghapus semua elemen yang tidak cocok dari daftar yang menerapkannya.

Ex.: list.retainAll(list1);

Dalam hal ini dari daftar, semua elemen yang tidak ada dalam list1 akan dihapus dan hanya yang tersisa yang umum antara list dan 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);

Keluaran:

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

CATATAN: Setelah mempertahankan Semua diterapkan pada daftar, daftar berisi elemen umum antara daftar dan 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

pertimbangkan dua daftar L1 dan L2

Dengan menggunakan Java8 kita dapat dengan mudah menemukannya

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


1

Jika Anda ingin melakukannya sendiri ..

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
OP meminta cara untuk menemukan elemen mana yang sama, bukan berapa elemen yang sama.
Brendon Dugan

@BrendonDugan - Itulah yang dilakukan kode ini. Daftar tersebut commonsberisi elemen umum. Loop-kedua mencetaknya di konsol. Saya tidak melihat di mana kode menghitung elemen umum.
Ajoy Bhatia

@AjoyBhatia - Ketika saya membuat komentar saya (pada 2013) kode hanya mengembalikan hitungan elemen umum.
Brendon Dugan

@BrendonDugan Oh, oke. Maaf soal itu. Saya harus ingat bahwa jawabannya dapat diedit di tempat tetapi komentar biasanya dibiarkan apa adanya, dalam urutan kronologis :-)
Ajoy Bhatia

0

Beberapa jawaban di atas mirip tapi tidak sama jadi posting sebagai jawaban baru.

Solusi:
1. Gunakan HashSet untuk menahan elemen yang perlu dihapus
2. Tambahkan semua elemen list1 ke HashSet
3. iterasi list2 dan hapus elemen dari HashSet yang ada di list2 ==> yang ada di list1 dan list2
4 Sekarang lakukan iterasi pada HashSet dan hapus elemen dari list1 (karena kita telah menambahkan semua elemen list1 untuk disetel), akhirnya, list1 memiliki semua elemen umum
Catatan: Kita dapat menambahkan semua elemen list2 dan dalam iterasi ke-3, kita harus menghapus elemen dari list2.

Kompleksitas waktu: O (n)
Kompleksitas Ruang: O (n)

Kode:

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

keluaran:

list1:[1, 2, 3, 4, 5]
list2:[1, 3, 5, 7]
toBeRemoveFromList1:[2, 4]
list1:[1, 3, 5]
collectionUtils:[1, 3, 5]
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.