두 목록의 공통 요소


95

ArrayList각각 세 개의 정수를 가진 두 개의 개체가 있습니다. 두 목록의 공통 요소를 반환하는 방법을 찾고 싶습니다. 아무도 내가 이것을 어떻게 얻을 수 있는지 아이디어가 있습니까?

답변:


161

사용 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

39

교차로 설정 작업을 사용할 수 있습니다. 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 개의 동일한 요소가 있다고 가정하면 문제가 조금 더 복잡해집니다. preserveAll은 l1에 두 번만 포함되어 있더라도 해당 요소의 3을 l3에 넣습니다.
demongolem

35

바퀴를 재발 명하는 이유는 무엇입니까? Commons 컬렉션 사용 :

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

이것은 훌륭한 솔루션이지만 위에서 언급했듯이 retainAll()반복되는 요소와 는 다른 동작이 있습니다. 따라서 문제에 접근하는 방법에 따라 하나는 정확하고 하나는 올바르지 않을 수 있습니다.
demongolem

18

Java 8의 Stream.filter()방법을 다음과 함께 사용 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 번 호출됩니다. 위의 내용이 선형 또는 2 차 시간으로 실행되는지 아는 사람이 있습니까?
Regorsmitz

1
그것은 * n 작업이 될 것입니다!
Lakshmikant Deshpande 2011

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

참고 : 목록에 preserveAll이 적용된 후 목록에는 list와 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

두 목록 L1 및 L2 고려

Java8을 사용하면 쉽게 찾을 수 있습니다.

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


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에는 공통 요소가 포함되어 있습니다. 두 번째 for 루프는 콘솔에 출력합니다. 코드가 공통 요소를 계산하는 위치를 알 수 없습니다.
Ajoy Bhatia

@AjoyBhatia-2013 년에 제가 댓글을 달았을 때 코드는 몇 개의 공통 요소 만 반환했습니다.
Brendon Dugan

@BrendonDugan 오, 알았어. 미안합니다. 나는 대답이 자리에서 편집 할 수 있지만 의견은 보통 :-) 연대순으로, 그대로 남아 있음을 유의하십시오
Ajoy 바 티아

0

위의 답변 중 일부는 유사하지만 동일하지는 않으므로 새 답변으로 게시합니다.

해결 방법 :
1. HashSet을 사용하여 제거해야하는 요소를 보유합니다
. 2. list1의 모든 요소를 ​​HashSet에 추가합니다.
3. list2를 반복하고 list1과 list2 모두에있는 list2 ==>에있는 HashSet에서 요소를 제거합니다.
4 . 이제 HashSet을 반복하고 list1에서 요소를 제거합니다 (list1의 모든 요소를 ​​설정에 추가 했으므로). 마지막으로 list1에는 모든 공통 요소가 있습니다.
참고 : list2의 모든 요소를 ​​추가 할 수 있으며 세 번째 반복에서는 다음에서 요소를 제거해야합니다. list2.

시간 복잡도 : 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]
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.