İki listedeki ortak öğeler


98

İki sahip ArrayListüç tamsayılar her Nesneleri. İki listenin ortak unsurlarını geri getirmenin bir yolunu bulmak istiyorum. Bunu nasıl başarabileceğime dair bir fikri olan var mı?

Yanıtlar:


164

Kullanın Collection#retainAll().

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

Değişikliklerin etkilenmesini önlemek istiyorsanız listA, yeni bir tane oluşturmanız gerekir.

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

RetainAll yeni bir liste döndürür mü? Keep'in çıktısını tempList.addAll (listA.retainAll (listB)) gibi yeni bir listeye kaydetmeye çalıştım; ama işe yaramıyor
zenitis

1
Arkasındaki bağlantıda Collection#retainAll()ve kod parçacıklarındaki yorumlarda yanıtlandığı gibi , hayır, öyle değil. Değişiklikler, yöntemi çağırdığınız listeye yansıtılır.
BalusC

Sorun şu ki, ortak liste boyut 3 ile başlatılıyor, ardından yalnızca bir veya iki öğe döndürerek boyutunu değiştirmeye çalışıyorsunuz. Önerdiğiniz şeyi deniyorum ve beni sınırların dışında döndürüyor.
zenitis

Bu yaklaşımda, eğer listB.retainAll (listA) yapacaksam ....... elemanının oluşum numarasını eşleştiremeyeceğim. Örneğin listA {2,3,5} ve listB {5 5} , listB'de artık {5,5} olacak ...... listA ve listB'yi {5} olarak karşılaştırdıktan sonra nihai sonucumu istiyorum. Lütfen bunu nasıl başarabileceğimizi önerin
NANCY

1
Zayıf koleksiyon nesnesi seçimi ile yapılırsa, bir UnsupportedOperationException oluşturabilir. ArrayList ile yukarıdaki örnek elbette işe yarıyor.
demongolem

39

ArrayListNesnelerinizle set kesişim işlemlerini kullanabilirsiniz .

Bunun gibi bir şey:

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

Şimdi, ve l3arasında yalnızca ortak öğeler olmalıdır .l1l2

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

6
Bu şekilde değişikliklerin de yansıtıldığını unutmayın l2. Muhtemelen List<Integer> l3 = new ArrayList<Integer>(l2);onun yerine söylemek istedin .
BalusC

Eğer l1'de 2 tane eleman ve l2'de aynı elemandan 3 tane varsa, sorun biraz daha karmaşık hale gelir. keepAll, l1'de yalnızca iki kez yer almasına rağmen, bu öğenin 3'ünü l3'e koyar.
demongolem

35

Neden tekerleği yeniden icat etmelisiniz? Kullanım Commons Koleksiyonları :

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

Bu harika bir çözüm, ancak yukarıda bahsettiğim gibi, retainAll()tekrarlanan öğelerden farklı bir davranışa sahip . Soruna nasıl yaklaştığınıza bağlı olarak büyük olasılıkla doğru ve yanlış.
demongolem

18

Java 8'in Stream.filter()yöntemini aşağıdakilerle birlikte kullanmak 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
Derleyici zekice bir şey yapmadıkça n kez çağrılacak bir O (n) işlemi gibi görünüyor. Yukarıdakilerin doğrusal mı yoksa ikinci dereceden zamanda mı çalıştığını bilen var mı?
Regorsmitz

1
Bu bir * n operasyonu olurdu!
Lakshmikant Deshpande

5

görüntü açıklamasını buraya girin

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

Bu kod soruyu yanıtlayabilirken, sorunun nasıl ve / veya neden çözüldüğüne ilişkin ek bağlam sağlamak , yanıtlayanın uzun vadeli değerini artıracaktır.
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

Çıktı [1, 5]


-İyileştirme Listeyi List <Integer> listA = asList (1, 5, 3, 4) olarak tanımlayabiliriz; Liste <Tamsayı> listB = asList (1, 5, 6, 7);
Rajeev Ranjan

4

"KeepAll" yöntemini kullanarak iki liste arasındaki ortak öğeleri elde edebilirsiniz. Bu yöntem, tüm eşleşmeyen öğeleri geçerli olduğu listeden kaldıracaktır.

Ex.: list.retainAll(list1);

Bu durumda listeden, list1'de olmayan tüm elemanlar kaldırılacak ve sadece list ile list1 arasında ortak olanlar kalacaktır.

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

Çıktı:

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

NOT: RetAll listeye uygulandıktan sonra, liste list ve list1 arasındaki ortak öğeyi içerir.


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

4

iki listeyi düşünün L1 ve L2

Java8 kullanarak kolayca bulabiliriz

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

Kendin yapmak istersen ...

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, kaç ortak unsur olduğunu değil, hangi unsurların ortak olduğunu bulmanın bir yolunu arıyordu.
Brendon Dugan

@BrendonDugan - Bu kodun yaptığı budur. Liste commons, ortak unsurları içerir. İkinci döngü, bunları konsolda yazdırır. Kodun ortak unsurları nerede saydığını görmüyorum.
Ajoy Bhatia

@AjoyBhatia - Yorumumu yaptığımda (2013'te) kod yalnızca bir dizi ortak öğe döndürdü.
Brendon Dugan

@BrendonDugan Oh, tamam. Bunun için üzgünüm. Cevabın yerinde düzenlenebileceğini, ancak yorumların genellikle kronolojik sırayla bırakıldığını unutmamalıyım :-)
Ajoy Bhatia

0

Yukarıdaki cevaplardan bazıları benzerdir ancak aynı değildir, bu yüzden yeni bir cevap olarak yayınlayın.

Çözüm:
1. Kaldırılması gereken öğeleri tutmak için HashSet kullanın
2. List1'in tüm öğelerini HashSet'e ekleyin
3. list2'yi yineleyin ve hem list1 hem de list2'de bulunan list2 ==> öğelerinde bulunan HashSet öğelerini kaldırın
4 Şimdi HashSet üzerinde yineleyin ve list1'den öğeleri kaldırın (ayarlamak için list1'in tüm öğelerini ekledik), son olarak, list1 tüm ortak öğelere sahiptir
Not: list2'nin tüm öğelerini ekleyebiliriz ve 3. yinelemede, liste2.

Zaman karmaşıklığı: O (n)
Uzay Karmaşıklığı: 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));

çıktı:

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

0

Kodun altında Listedeki ortak öğeleri kaldırın

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

Ortak öğeleri alın

List<String> result = list1.stream()
                .distinct()
                .filter(list::contains)
                .collect(Collectors.toList());
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.