한 목록에 다른 요소가 포함되어 있는지 확인


105

개체가 다른 두 개의 목록이 있습니다.

List<Object1> list1;
List<Object2> list2;

특정 속성 (Object1 및 Object2에는 (다른 것 중에서), 하나의 상호 속성 (Long 유형 포함), attributeSame이라는 이름의)을 기반으로 list1의 요소가 list2에 있는지 확인하고 싶습니다.

지금은 이렇게합니다.

boolean found = false;
for(Object1 object1 : list1){
   for(Object2 object2: list2){
       if(object1.getAttributeSame() == object2.getAttributeSame()){
           found = true;
           //also do something
       }
    }
    if(!found){
        //do something
    }
    found = false;
}

그러나 나는 이것을하는 더 좋고 더 빠른 방법이 있다고 생각합니다 :) 누군가 그것을 제안 할 수 있습니까?

감사!


첫째, found = true로 설정하면; 그런 다음 간단히 중단하십시오. 또는 루프에서 나오십시오
jsist 2013-08-03

stackoverflow.com/questions/5187888/... . 또한, 빠른 검색을위한 ... 이진 검색을 사용하여 시도하고 상황에 적합하게 당신의 DS를 변경
jsist

그들은 Object 외에 공통된 부모를 공유합니까?
Woot4Moo

@ Woot4Moo 아니, 그들은하지 않습니다
Ned

답변:


220

기본 동등성을 테스트해야하는 경우 한 줄의 입력 목록을 수정하지 않고 기본 JDK로 수행 할 수 있습니다.

!Collections.disjoint(list1, list2);

특정 속성을 테스트해야하는 경우 더 어렵습니다. 기본적으로

list1.stream()
   .map(Object1::getProperty)
   .anyMatch(
     list2.stream()
       .map(Object2::getProperty)
       .collect(toSet())
       ::contains)

... 이는 고유 한 값을 수집하고 list2각 값의 list1존재 여부를 테스트합니다 .


1
둘 다 두 개의 다른 객체이기 때문에 항상 false를 반환하지 않습니까?
Venki

2
음 .. 아니야? 두 컬렉션 사이에 서로 equals () 객체가 없는지 테스트합니다.
Louis Wasserman

13
또한 목록의 경우 O (n * m); 비교하기 전에 list1a 에 복사하려는 경우 Set추가 RAM 비용으로 O (n) + O (m), 즉 O (n + m)을 얻을 수 있습니다. 속도 나 메모리 중에서 선택하는 문제입니다.
Haroldo_OK

이것은 "List <Person> list1; List <Person> list2"인 경우에만 작동하지만 List <Person> list1과 같은 두 개의 다른 개체 또는 데이터 유형에서는 작동하지 않습니다. List <직원> list2.
whoami

물론 이것은 @Zephyr 시나리오에서 작동하지 않을 것입니다. 그게 전부입니다!
Syed Siraj Uddin 2019

38

Apache Commons CollectionUtils를 사용할 수 있습니다 .

if(CollectionUtils.containsAny(list1,list2)) {  
    // do whatever you want
} else { 
    // do other thing 
}  

이것은 사용자 정의 개체에 대해 같음 기능을 적절하게 오버로드했다고 가정합니다.


9
4 년이 지났고 나는 또한 패키지와 기능을 명시 적으로 언급했습니다.
Woot4Moo

1
jdk 전용 솔루션이있을 때 아파치 커먼즈에 대한 반대 투표
ohcibi

9
@ohcibi Java에는 로거가 내장되어 있으므로 Log4j 및 Log4j2 사용을 제안하는 사람들을 비워 두어야합니다.
Woot4Moo

1
@ Woot4Moo에 따라 다릅니다. OP 문제를 해결하기 위해 Log4j를 사용할 이유가있는 경우 반대 투표 할 이유가 없습니다. 이 경우 아파치 커먼즈는 아파치 커먼즈를 제안하는 답변의 99 % 에서처럼 단순히 쓸모없는 팽창 일 것입니다.
ohcibi

1
@ohcibi이지만 이미 Apache commons를 사용하고 있다면 실제로 부 풀지 않습니다. 이것은 좋은 대답이었습니다.
vab2048

20

Narendra의 논리를 줄이려면 다음을 사용할 수 있습니다.

boolean var = lis1.stream().anyMatch(element -> list2.contains(element));

3
이 답변은 저평가되어 있습니다.
Kervvv

1
원하는 경우 조금 더 줄일 수 있습니다.list1.stream().anyMatch(list2::contains);
tarka

9

하나의 방법Collection이름은 retainAll있지만, 일부 가진 부작용 당신을 위해 참조

지정된 컬렉션에 포함 된이 목록의 요소 만 유지합니다 (선택적 작업). 즉, 지정된 컬렉션에 포함되지 않은 모든 요소를이 목록에서 제거합니다.

이 목록이 호출의 결과로 변경된 경우 true

같은

boolean b = list1.retainAll(list2);

5

Loius 대답이 맞습니다. 예를 추가하고 싶습니다.

listOne.add("A");
listOne.add("B");
listOne.add("C");

listTwo.add("D");
listTwo.add("E");
listTwo.add("F");      

boolean noElementsInCommon = Collections.disjoint(listOne, listTwo); // true

1
두 번째 목록에 'A'요소를 추가하면 listTwo.add ( "A"); 비록 Collections.disjoint (listOne, listTwo); true를 반환합니다.
Sairam Kukadala

2

더 빠른 방법은 추가 공간이 필요합니다.

예를 들면 :

  1. 한 목록의 모든 항목을 HashSet에 넣습니다 (object.getAttributeSame ()을 사용하려면 직접 해시 함수를 구현해야 함)

  2. 다른 목록으로 이동하여 HashSet에 항목이 있는지 확인하십시오.

이런 식으로 각 개체는 최대 한 번 방문합니다. HashSet은 O (1)에있는 모든 객체를 확인하거나 삽입하기에 충분히 빠릅니다.


2

JavaDoc에 따르면 .contains(Object obj):

이 목록에 지정된 요소가 포함 된 경우 true를 반환합니다. 보다 공식적으로,이 목록에 (o == null? e == null : o.equals (e))와 같은 요소 e가 하나 이상 포함 된 경우에만 true를 반환합니다.

따라서 .equals()주어진 객체에 대한 메서드를 재정의하면 다음 을 수행 할 수 있습니다.if(list1.contains(object2))...

요소가 고유 한 경우 (즉, 다른 속성이있는 경우) .equals()및을 재정의하고 .hashcode()모든 것을 HashSets. 이렇게하면 일정한 시간에 다른 요소가 포함되어 있는지 확인할 수 있습니다.


2

더 빨리 만들기 위해 휴식을 추가 할 수 있습니다. 그런 식으로 found가 true로 설정되면 루프가 중지됩니다.

boolean found = false;
for(Object1 object1 : list1){
   for(Object2 object2: list2){
       if(object1.getAttributeSame() == object2.getAttributeSame()){
           found = true;
           //also do something  
           break;
       }
    }
    if(!found){
        //do something
    }
    found = false;
}

키가 attributeSame 인 목록 대신 맵이있는 경우 두 번째 맵에 해당 값이 있는지 여부에 따라 한 맵의 값을 더 빨리 확인할 수 있습니다.


안녕하세요 Tom, 알아 주셔서 감사합니다! 예, 입력하는 동안 "휴식"을 잊었습니다. 하지만 알고리즘이 있을지도 모르거나이 목록을 다른 컬렉션으로 변경해야한다고 생각했습니다.
Ned

O (n * m)보다 더 좋은 것은 없습니까?
Woot4Moo

.getAttributeSame ()?
받는다는ツ

Object1 및 Object2의 getAttributeSame () 메소드 구현은 제공되지 않지만 질문 및 답변과 관련이 없습니다. 두 클래스 모두에있는 속성 (attributeSame, Long) 만 반환합니다.

0

보유한 데이터 유형을 정의 할 수 있습니까? 빅 데이터인가요? 정렬되어 있습니까? 데이터에 따라 다른 효율성 접근법을 고려해야한다고 생각합니다.

예를 들어 데이터가 크고 정렬되지 않은 경우 인덱스별로 두 목록을 함께 반복하고 각 목록 속성을 다른 목록 도우미에 저장할 수 있습니다. 그런 다음 도우미 목록의 현재 속성으로 교차 확인할 수 있습니다.

행운을 빕니다

편집 : 그리고 나는 동등한 과부하를 권장하지 않습니다. 그것은 위험하고 아마도 당신의 객체 oop 의미에 위배됩니다.



0

을 사용하면 java 8다음과 같이 한 목록에 다른 목록의 요소가 포함되어 있는지 확인할 수 있습니다.

boolean var = lis1.stream().filter(element -> list2.contains(element)).findFirst().isPresent();

0

목록에 요소가 있는지 확인하려면 contains 메소드를 사용하십시오.

if (list1.contains(Object o))
{
   //do this
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.