องค์ประกอบทั่วไปในสองรายการ


101

ฉันมีสองArrayListวัตถุที่มีจำนวนเต็มสามตัว ฉันต้องการหาวิธีคืนค่าองค์ประกอบทั่วไปของทั้งสองรายการ มีใครคิดว่าฉันจะบรรลุเป้าหมายนี้ได้อย่างไร?

คำตอบ:


166

ใช้Collection#retainAll().

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

หากคุณต้องการหลีกเลี่ยงไม่ให้การเปลี่ยนแปลงได้รับผลกระทบlistAคุณต้องสร้างการเปลี่ยนแปลงใหม่

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

RetainAll ส่งคืนรายการใหม่? ฉันพยายามจัดเก็บผลลัพธ์ของการเก็บรักษาไว้ในรายการใหม่เช่นนั้น tempList.addAll (listA.retainAll (listB)); แต่ไม่ได้ผล
zenitis

1
ตามที่ตอบไว้ในลิงค์ด้านหลังCollection#retainAll()และความคิดเห็นในส่วนย่อยของโค้ดไม่มันไม่ได้ การเปลี่ยนแปลงจะแสดงในรายการที่คุณกำลังเรียกใช้เมธอด
BalusC

ปัญหาคือรายการทั่วไปเริ่มต้นด้วยขนาด 3 จากนั้นคุณพยายามเปลี่ยนขนาดโดยส่งคืนองค์ประกอบเพียงหนึ่งหรือสององค์ประกอบ ฉันลองทำตามที่คุณแนะนำและมันส่งคืนฉันนอกขอบเขต
zenitis

ในวิธีนี้ฉันจะไม่สามารถจับคู่จำนวนองค์ประกอบที่เกิดขึ้น ....... พูดเช่น listA {2,3,5} และ listB {5 5} ถ้าฉันจะทำ listB.retainAll (listA) ตอนนี้ listB จะมี {5,5} ...... ฉันต้องการให้ผลลัพธ์สุดท้ายของฉันหลังจากเปรียบเทียบ listA และ listB เป็น {5} กรุณาแนะนำว่าเราจะบรรลุเป้าหมายนี้ได้อย่างไร
NANCY

1
หากเลือกวัตถุคอลเลกชันที่ไม่ดีอาจทำให้ UnsupportedOperationException ตัวอย่างข้างต้นกับ ArrayList ได้ผลแน่นอน
demongolem

40

คุณสามารถใช้การดำเนินการจุดตัดกับArrayListวัตถุของคุณ

สิ่งนี้:

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

ตอนนี้l3ควรจะมีเพียงองค์ประกอบร่วมกันระหว่างและl1l2

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

6
โปรดทราบว่าวิธีนี้จะแสดงการเปลี่ยนแปลงด้วยl2เช่นกัน คุณอาจหมายถึงพูดList<Integer> l3 = new ArrayList<Integer>(l2);แทน
BalusC

ปัญหาจะยุ่งขึ้นเล็กน้อยถ้าบอกว่า l1 มี 2 ขององค์ประกอบและ l2 มี 3 องค์ประกอบเดียวกัน ผลตอบแทนทั้งหมดทำให้ 3 ขององค์ประกอบนั้นใน l3 แม้ว่าจะมีเพียงสองครั้งใน l1
demongolem

35

ทำไมต้องคิดค้นล้อใหม่? ใช้Commons Collections :

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

นี่เป็นวิธีแก้ปัญหาที่ยอดเยี่ยม แต่อย่างที่ฉันได้กล่าวไปข้างต้นมันมีลักษณะการทำงานที่แตกต่างจากretainAll()องค์ประกอบซ้ำ ๆ มีแนวโน้มว่าจะถูกต้องและอย่างใดอย่างหนึ่งไม่ถูกต้องขึ้นอยู่กับวิธีที่คุณแก้ไขปัญหา
demongolem

19

ใช้Stream.filter()วิธีการของ Java 8 ร่วมกับ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
ประกอบด้วยดูเหมือนว่าจะเป็นการดำเนินการ O (n) ซึ่งจะเรียกว่า n ครั้งเว้นแต่คอมไพเลอร์จะทำอะไรที่ฉลาด มีใครรู้บ้างว่าข้างต้นทำงานในเวลาเชิงเส้นหรือกำลังสอง?
Regorsmitz

1
มันจะเป็นการดำเนินการ * n!
Lakshmikant Deshpande

5

ป้อนคำอธิบายภาพที่นี่

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

แม้ว่ารหัสนี้อาจตอบคำถามได้ แต่การให้บริบทเพิ่มเติมเกี่ยวกับวิธีการและ / หรือเหตุผลในการแก้ปัญหาจะช่วยเพิ่มมูลค่าในระยะยาวของคำตอบ
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

เอาต์พุต [1, 5]


- การปรับปรุงเราสามารถกำหนดรายการเป็น List <Integer> listA = asList (1, 5, 3, 4); รายการ <Integer> listB = asList (1, 5, 6, 7);
Rajeev Ranjan

4

คุณสามารถรับองค์ประกอบทั่วไประหว่างสองรายการโดยใช้เมธอด "RetainAll" วิธีนี้จะลบองค์ประกอบที่ไม่ตรงกันทั้งหมดออกจากรายการที่ใช้

Ex.: list.retainAll(list1);

ในกรณีนี้จากรายการองค์ประกอบทั้งหมดที่ไม่อยู่ใน list1 จะถูกลบออกและจะเหลือเพียงองค์ประกอบซึ่งเป็นเรื่องธรรมดาระหว่าง list และ 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);

เอาท์พุต:

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

หมายเหตุ: หลังจากใช้งาน RetainAll ในรายการรายการจะมีองค์ประกอบทั่วไประหว่างรายการและรายการ 1



4

พิจารณาสองรายการ L1 ans L2

การใช้ Java8 เราสามารถค้นหาได้อย่างง่ายดาย

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

ในกรณีที่อยากทำเอง ..

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 กำลังขอวิธีค้นหาว่าองค์ประกอบใดเป็นเรื่องธรรมดาไม่ใช่จำนวนองค์ประกอบทั่วไปที่มี
Brendon Dugan

@BrendonDugan - นั่นคือสิ่งที่รหัสนี้ทำ รายการcommonsประกอบด้วยองค์ประกอบทั่วไป สำหรับลูปที่สองจะพิมพ์บนคอนโซล ฉันไม่เห็นว่าโค้ดกำลังนับองค์ประกอบทั่วไปอยู่ที่ใด
Ajoy Bhatia

@AjoyBhatia - เมื่อฉันแสดงความคิดเห็น (ในปี 2013) รหัสจะส่งคืนจำนวนองค์ประกอบทั่วไปเท่านั้น
Brendon Dugan

@BrendonDugan โอ้ตกลง ขอโทษสำหรับเรื่องนั้น. ฉันควรจำไว้ว่าคำตอบสามารถแก้ไขได้ แต่ความคิดเห็นมักจะถูกทิ้งไว้ตามที่เป็นอยู่ :-)
Ajoy Bhatia

0

คำตอบด้านบนบางคำตอบคล้ายกัน แต่ไม่เหมือนกันดังนั้นจึงโพสต์เป็นคำตอบใหม่

วิธีแก้ไข:
1. ใช้ HashSet เพื่อเก็บองค์ประกอบที่จำเป็นต้องลบออก
2. เพิ่มองค์ประกอบทั้งหมดของ list1 ไปที่ HashSet
3. วนซ้ำ list2 และลบองค์ประกอบออกจาก HashSet ซึ่งมีอยู่ใน list2 ==> ซึ่งมีอยู่ทั้ง list1 และ list2
4 ตอนนี้ทำซ้ำบน HashSet และลบองค์ประกอบออกจาก list1 (เนื่องจากเราได้เพิ่มองค์ประกอบทั้งหมดของ list1 เพื่อตั้งค่า) ในที่สุด list1 ก็มีองค์ประกอบทั่วไปทั้งหมด
หมายเหตุ: เราสามารถเพิ่มองค์ประกอบทั้งหมดของ list2 และในการทำซ้ำครั้งที่ 3 เราควรลบองค์ประกอบออกจาก รายการ 2.

ความซับซ้อนของเวลา: O (n)
ความซับซ้อนของพื้นที่: O (n)

รหัส:

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

เอาท์พุท:

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

0

ด้านล่างรหัสลบองค์ประกอบทั่วไปในรายการ

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

ดึงองค์ประกอบทั่วไป

List<String> result = list1.stream()
                .distinct()
                .filter(list::contains)
                .collect(Collectors.toList());

0
public static <T> List<T> getCommonElements(
            java.util.Collection<T> a,
            java.util.Collection<T> b
            ) {
        if(a==null && b==null) return new ArrayList<>();
        if(a!=null && a.size()==0) return new ArrayList<>(b);           
        if(b!=null && b.size()==0) return new ArrayList<>(a);
        
        Set<T> set= a instanceof HashSet?(HashSet<T>)a:new HashSet<>(a);
        return b.stream().filter(set::contains).collect(Collectors.toList());
    }

เพื่อประสิทธิภาพเวลาที่ดีขึ้นโปรดใช้ HashSet (O (1) look up) แทน List (O (n) look ups)

ความซับซ้อนของเวลา - O (b) ความซับซ้อนของพื้นที่ - O (a)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.