Java 세트의 '포함'과 같은 것이 있습니까?


307

같은 유형의 A와 B 두 세트가 있습니다.

A에 세트 B의 요소가 있는지 찾아야합니다.

세트를 반복하지 않고 가장 좋은 방법은 무엇입니까? 설정 라이브러리가 contains(object)하고 containsAll(collection)있지만 containsAny(collection).


4
효율성이나 코드 청결을 위해 반복을 피하려고 노력하고 있습니까?
yshavit

답변:


527

Collections.disjoint(A, B)작동 하지 않습니까? 설명서에서 :

지정된 true두 컬렉션에 공통 요소가없는 경우를 반환 합니다.

따라서 false컬렉션에 공통 요소가 포함되어 있으면 메서드가 반환 됩니다.


17
세트 중 하나를 수정하지 않거나 새 세트를 작성하므로 다른 솔루션보다 선호하십시오.
devconsole

7
표준 JRE이며 설정뿐만 아니라 모든 컬렉션에서 작동합니다.
Pierre Henry

4
나는 이것이 가장 빠르다고 생각하지 않으며 교차점의 첫 번째 요소가 발견 될 때 단락되지 않습니다.
벤 호너

7
실제로 첫 번째 공통 요소를 발견하자마자 단락 될 것입니다
Xipo


156

Stream::anyMatch

Java 8부터 사용할 수 있습니다 Stream::anyMatch.

setA.stream().anyMatch(setB::contains)

1
이것이 바로 내가 찾던 것입니다! 감사합니다 :-) 또한 :: 구문으로 변수를 사용할 수 있다는 것을 몰랐습니다!
dantiston

1
@blevert, anyMatch 내부에서 어떤 일이 발생하는지 설명해 주시겠습니까?
Cristiano

7
@Cristiano는 여기에서 anyMatch모든 요소를 ​​스트리밍하고 모든 요소를 setA호출 setB.contains()합니다. 요소에 대해 "true"가 리턴되면 전체 표현식이 true로 평가됩니다. 이것이 도움이 되었기를 바랍니다.
Alex Vulaj


31

세트에 containsAny를 구현하는 좋은 방법은 Guava Sets.intersection ()을 사용하는 것 입니다.

containsAny를 반환 boolean하므로 호출은 다음과 같습니다.

Sets.intersection(set1, set2).isEmpty()

세트가 분리되어 있으면 true를, 그렇지 않으면 false를 반환합니다. 원래 세트를 수정하지 않기 위해 복제를 할 필요가 없기 때문에이 시간의 복잡성은 retainAll보다 약간 낫습니다.


3
이 방법을 사용하는 유일한 단점은 구아바 라이브러리를 포함해야한다는 것입니다. 구글 컬렉션 API는 매우 강력하기 때문에 불리하지 않다고 생각합니다.
Mohammad Adnan

@DidierL이 기능을 포함한 대부분의 Guava Collections 유틸리티 기능 은 데이터 구조의 를 반환 합니다 . 따라서이 경우 걱정할 "세트 만들기"가 없습니다. 구현은 여기에서 읽거나 javadoc을 참조하십시오. google.github.io/guava/releases/21.0/api/docs/com/google/common/…
chut

@MohammadAdnan 또 다른 단점은 전체 교차점을 계산한다는 것입니다. set1과 set2가 매우 큰 경우 공통 항목이 있는지 확인하는 것보다 CPU와 메모리 측면에서 훨씬 많은 리소스를 소비하게됩니다.
Marxama


16

org.apache.commons.collections.CollectionUtils를 사용합니다.

CollectionUtils.containsAny(someCollection1, someCollection2)

그게 다야! 하나 이상의 요소가 두 컬렉션에 모두 있으면 true를 반환 합니다 .

사용하기 쉽고 함수의 이름이 더 암시 적입니다.


5

retainAll()Set 인터페이스에서 사용하십시오 . 이 방법은 두 세트에서 공통 인 요소의 교차점을 제공합니다. 자세한 내용은 API 문서를 참조하십시오.


반복을 피하는 것이 효율성을위한 것이라면 retainAll도움이되지 않을 것입니다. AbstractCollection반복 구현 .
yshavit

1
yshavit이 맞습니다. OP가 어떤 요소가 두 세트 모두에 있는지 확인하려고 하면 적절한 알고리즘은 O(1)최상의 경우에 실행 시간을 갖는 반면 retainAll라인의 선을 따라 무언가를 가질 것입니다 O(N)(1 세트의 크기에 따라 다름) 최고의 실행 시간.
Zéychin

3

HashMap세트 A에서 생성 한 다음 세트 B를 반복하고 B의 요소가 A에 있는지 확인 하는 것이 좋습니다 . O(|A|+|B|)충돌이 없을 때 시간에 retainAll(Collection<?> c)실행되지만 O(|A|*|B|)시간에 실행해야합니다 .


3

그렇게하는 약간 거친 방법이 있습니다. A 집합이 호출보다 일부 B 요소를 포함하는 경우에만

A.removeAll(B)

A 세트를 수정합니다. 이 상황에서 removeAll은 true를 리턴합니다 ( removeAll docs에 명시된대로 ). 그러나 아마도 A 세트를 수정하고 싶지 않아서 다음과 같이 사본에 대한 행동을 생각할 수 있습니다.

new HashSet(A).removeAll(B)

집합이 고유하지 않은 경우 즉, 비어 있지 않은 교차가 있으면 반환 값이 true가됩니다.

Apache Commons Collection 도 참조하십시오


2

retainAll 메소드 를 사용 하여 두 세트의 교차점을 얻을 수 있습니다 .


대부분의 경우 원본 세트를 보관해야하므로 사용 retainAll하려면 원본 세트를 복사해야합니다. 그런 다음 Zéychin이HashSet 제안한대로 사용 하는 것이 더 효율적 입니다.
Petr Pudlák

상태 확인이 아니라 상태 변경입니다.
Ben
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.