[java] 서로 다른 두 목록에 정확히 동일한 요소가 포함되어 있는지 확인하는 간단한 방법?

표준 Java 라이브러리에서 두 List에 정확히 동일한 요소가 포함되어 있는지 확인하는 가장 간단한 방법은 무엇입니까?

두 List가 동일한 인스턴스인지 여부는 중요하지 않으며 List의 type 매개 변수가 다른 경우에도 중요하지 않습니다.

예 :

List list1
List<String> list2;
// ... construct etc

list1.add("A");
list2.add("A");
// the function, given these two lists, should return true

내가 아는 얼굴에 나를 쳐다 보는 무언가가있을 것입니다 🙂


편집 : 명확히하기 위해, 정확히 동일한 요소와 요소 수를 순서대로 찾고있었습니다.



답변

순서에 관심이 있다면 equals 메소드를 사용하십시오.

list1.equals(list2)

javadoc에서 :

지정된 객체와이리스트가 동일한 지 어떤지를 비교합니다. 지정된 객체도 목록이고 두 목록의 크기가 동일하고 두 목록의 모든 해당 요소 쌍이 동일한 경우에만 true를 반환합니다. ((e1 == null? e2 == null : e1.equals (e2)) 인 경우 두 요소 e1과 e2는 같습니다.) 즉, 동일한 순서로 동일한 요소를 포함하는 두 목록은 동일하도록 정의됩니다. . 이 정의는 equals 메소드가 List 인터페이스의 다른 구현에서 올바르게 작동하도록합니다.

순서와 무관하게 확인하려면 모든 요소를 ​​세트로 복사하고 결과 세트에서 equals를 사용할 수 있습니다.

public static <T> boolean listEqualsIgnoreOrder(List<T> list1, List<T> list2) {
    return new HashSet<>(list1).equals(new HashSet<>(list2));
}

이 방법의 한계는 순서를 무시할뿐만 아니라 중복 요소의 빈도도 무시한다는 것입니다. 예를 들어, list1“”A “,”B “,”A “]이고 list2” “A”, “B”, “B”] 인 경우 Set접근 방식은 동일하다고 간주합니다.

순서에 민감하지 않지만 복제 빈도에 민감한 경우 다음 중 하나를 수행 할 수 있습니다.


답변

나는 그것이 자신의 대답을 보증한다고 생각하는 의견에 많은 것을 게시했습니다.

모두가 여기에서 말했듯이 equals () 사용은 순서에 달려 있습니다. 주문에 신경 쓰지 않으면 3 가지 옵션이 있습니다.

옵션 1

사용하십시오 containsAll(). 이 옵션은 최악의 경우 성능을 제공하기 때문에 이상적이지 않습니다 .O (n ^ 2).

옵션 2

이에 대한 두 가지 변형이 있습니다.

2a) 목록의 순서를 유지하는 데 신경 쓰지 않는다면 Collections.sort()두 목록 모두에서 사용 하십시오. 그런 다음을 사용하십시오 equals(). 두 가지 정렬을 수행 한 다음 O (n) 비교를 수행하기 때문에 이것은 O (nlogn)입니다.

2b) 목록 순서를 유지해야하는 경우 두 목록을 먼저 복사 할 수 있습니다. 그런 다음 복사 된 목록 모두에서 솔루션 2a 를 사용할 수 있습니다 . 그러나 복사 비용이 매우 비싸면 매력적이지 않을 수 있습니다.

이것은 다음으로 이어진다 :

옵션 3

요구 사항이 파트 2b 와 동일 하지만 복사 비용이 너무 비싼 경우 TreeSet을 사용하여 정렬을 수행 할 수 있습니다. 각 목록을 자체 TreeSet에 덤프하십시오. 세트로 정렬되며 원래 목록은 그대로 유지됩니다. 그런 다음 equals()TreeSets 에서 비교를 수행하십시오 . TreeSets들에서 O (nlogn) 시간을 구축 할 수 있고,이 equals()O (N)이다.

선택해라 :-).

편집 : 나는 Laurence Gonsalves가 지적한것과 동일한 경고를 거의 잊었습니다. TreeSet 구현은 중복을 제거합니다. 중복에 관심이 있다면 일종의 정렬 된 다중 집합이 필요합니다.


답변

Apache Commons Collections를 사용하고 있거나 사용하기를 좋아하는 경우 CollectionUtils.isEqualCollection 을 사용할 수 있습니다. “주어진 Collections가 정확히 동일한 카디널리티를 가진 동일한 동일한 요소를 포함하는 경우 true를 반환합니다.”


답변

파티에 매우 늦었지만이 null 안전 검사를 추가하고 싶었습니다.

Objects.equals(list1, list2)


답변

나는 이것이 오래된 스레드라는 것을 알고 있지만 다른 대답은 내 유스 케이스를 완전히 해결하지 못했습니다 (구아바 멀티 세트가 똑같이 할 수도 있지만 여기에는 예가 없습니다). 내 서식을 변명 해주세요. 나는 여전히 스택 교환에 게시하는 것에 익숙하지 않습니다. 또한 오류가 있으면 알려주세요

당신이 말할 수 있습니다 List<T>A와 List<T>B를하고 그들이 다음과 같은 조건과 동일한 경우 확인하려면 :

1) O (n) 예상 실행 시간
2) 평등은 다음과 같이 정의됩니다. a 또는 b의 모든 요소에 대해 a에서 요소가 발생하는 횟수는 b에서 요소가 발생하는 횟수와 같습니다. 요소 평등은 T.equals ()로 정의됩니다

private boolean listsAreEquivelent(List<? extends Object> a, List<? extends Object> b) {
    if(a==null) {
        if(b==null) {
            //Here 2 null lists are equivelent. You may want to change this.
            return true;
        } else {
            return false;
        }
    }
    if(b==null) {
        return false;
    }
    Map<Object, Integer> tempMap = new HashMap<>();
    for(Object element : a) {
        Integer currentCount = tempMap.get(element);
        if(currentCount == null) {
            tempMap.put(element, 1);
        } else {
            tempMap.put(element, currentCount+1);
        }
    }
    for(Object element : b) {
        Integer currentCount = tempMap.get(element);
        if(currentCount == null) {
            return false;
        } else {
            tempMap.put(element, currentCount-1);
        }
    }
    for(Integer count : tempMap.values()) {
        if(count != 0) {
            return false;
        }
    }
    return true;
}

우리가 해시 맵에 O (2 * n) 삽입을하고 O (3 * n) 해시 맵 선택을 수행하기 때문에 실행 시간은 O (n)입니다. 이 코드를 완전히 테스트하지 않았으므로주의하십시오 🙂

//Returns true:
listsAreEquivelent(Arrays.asList("A","A","B"),Arrays.asList("B","A","A"));
listsAreEquivelent(null,null);
//Returns false:
listsAreEquivelent(Arrays.asList("A","A","B"),Arrays.asList("B","A","B"));
listsAreEquivelent(Arrays.asList("A","A","B"),Arrays.asList("A","B"));
listsAreEquivelent(Arrays.asList("A","A","B"),null);


답변

순서가 같을 필요는 없지만 동일한 값의 배수를 지원하는이 버전을 사용해보십시오. 각 값의 수량이 같은 경우에만 일치합니다.

public boolean arraysMatch(List<String> elements1, List<String> elements2) {
    // Optional quick test since size must match
    if (elements1.size() != elements2.size()) {
        return false;
    }
    List<String> work = newArrayList(elements2);
    for (String element : elements1) {
        if (!work.remove(element)) {
            return false;
        }
    }
    return work.isEmpty();
}


답변

List의 equals 메소드가이를 수행하고 List가 정렬되므로 두 List가 동일한 순서로 동일한 요소를 가져야합니다.

return list1.equals(list2);