2012-05-25 5 views
10

구현할 수있는 특정 기준에 따라 컬렉션에 중복 항목을 찾을 수있는 도구 또는 라이브러리가 있습니까?컬렉션에서 중복 항목 찾기


분명히하기 : 특정 기준에 따라 서로 항목을 비교하고 싶습니다. 그래서 true 또는 false만을 반환하는 Predicate은 충분하지 않다고 생각합니다.


나는 equals을 사용할 수 없습니다.

+1

어떤 방식으로 중복 제거 기준을 지정 하시겠습니까? 이진 술어로서? – NPE

+1

중복을 찾거나 * 제거 * 하시겠습니까? –

+0

@ AndyThomas-Cramer 실제로 복제본이 있는지를 아는 것만으로도 충분합니다. –

답변

2

나는 IEqualityComparer<T> 인터페이스와 비슷한 새 인터페이스를 .NET에 만들었습니다.

그런 다음 EqualityComparator<T> 다음은 중복을 감지하는 다음 방법을 전달합니다.

public static <T> boolean hasDuplicates(Collection<T> collection, 
     EqualsComparator<T> equalsComparator) { 
    List<T> list = new ArrayList<>(collection); 
    for (int i = 0; i < list.size(); i++) { 
     T object1 = list.get(i); 
     for (int j = (i + 1); j < list.size(); j++) { 
      T object2 = list.get(j); 
      if (object1 == object2 
        || equalsComparator.equals(object1, object2)) { 
       return true; 
      } 
     } 
    } 
    return false; 
} 

이렇게하면 원하는대로 비교할 수 있습니다.

2

지도를 사용할 수 있으며 컬렉션을 반복하면서 요소를지도에 넣습니다 (조건부가 키를 형성합니다). 이미 항목이 있으면 중복을 발견했습니다.

자세한 내용은 여기를 참조하십시오 Finding duplicates in a collection

7

이 기준의 의미에 따라 달라집니다

당신의 기준은 항상 지정된 클래스에 대해 동일한, 그리고에 고유의 경우 기본 개념을 사용하는 경우 equalshashCode을 구현하고 세트를 사용해야합니다.

은 당신의 기준은 상황에 맞는에 의존하는 경우, org.apache.commons.collections.CollectionUtils.select(java.util.Collection, org.apache.commons.collections.Predicate) 당신을위한 적합한 솔루션이 될 수 있습니다.

+0

임의의 기준이 아닌 서로간에 항목을 비교하고 싶습니다. –

4

중복을 찾으려면 컬렉션을 배열로 던지고 조건을 구현하는 Comparator를 통해 배열을 정렬 한 다음 배열을 선형 적으로 살펴보고 인접한 중복에 대해서.

여기 (안 테스트) 스케치입니다 :

MyComparator myComparator = new MyComparator(); 
    MyType[] myArray = myList.toArray(); 
    Arrays.sort(myArray, myComparator); 
    for (int i = 1; i < myArray.length; ++i) { 
     if (0 == myComparator.compare(myArray[i - 1], myArray[i])) { 
     // Found a duplicate! 
     } 
    } 

편집 : 귀하의 코멘트에서, 당신은 단지 중복이 있는지 알고 싶습니다. 위의 접근 방식도 이와 관련됩니다. 그러나 사용자 정의 Comparator를 사용하여 java.util.SortedSet을 생성하면됩니다. 여기 스케치는 다음과 같습니다

MyComparator myComparator = new MyComparator(); 
    TreeSet treeSet = new TreeSet(myComparator); 
    treeSet.addAll(myCollection); 
    boolean containsDuplicates = (treeSet.size() != myCollection.size()); 
3

당신은 임의의 유형의 객체 간의 중복을 검색 할 자바 설정을 적용 할 수 있습니다 : 당신의 기준에 따라 평등을 평가하는 개인 래퍼에서 대상 클래스를 포장하고 래퍼의 세트를 구성 .

다음은이 기술을 설명하는 다소 긴 예제입니다. 동일한 이름을 가진 두 사람이 같다고 생각하기 때문에 5 개의 객체 배열에서 3 개의 중복을 감지합니다.

import java.util.*; 
import java.lang.*; 

class Main { 
    static class Person { 
     private String first; 
     private String last; 
     public String getFirst() {return first;} 
     public String getLast() {return last;} 
     public Person(String f, String l) { 
      first = f; 
      last = l; 
     } 
     public String toString() { 
      return first+" "+last; 
     } 
    } 
    public static void main (String[] args) throws java.lang.Exception { 
     List<Person> people = new ArrayList<Person>(); 
     people.add(new Person("John", "Smith")); 
     people.add(new Person("John", "Scott")); 
     people.add(new Person("Jack", "First")); 
     people.add(new Person("John", "Walker")); 
     people.add(new Person("Jack", "Black")); 
     Set<Object> seen = new HashSet<Object>(); 
     for (Person p : people) { 
      final Person thisPerson = p; 
      class Wrap { 
       public int hashCode() { return thisPerson.getFirst().hashCode(); } 
       public boolean equals(Object o) { 
        Wrap other = (Wrap)o; 
        return other.wrapped().getFirst().equals(thisPerson.getFirst()); 
       } 
       public Person wrapped() { return thisPerson; } 
      }; 
      Wrap wrap = new Wrap(); 
      if (seen.add(wrap)) { 
       System.out.println(p + " is new"); 
      } else { 
       System.out.println(p + " is a duplicate"); 
      } 
     } 
    } 
} 

이 예제는 ideone [link]에서 재생할 수 있습니다.

+0

+1 : 흥미 롭습니다! 효율성을 전혀 모릅니다. – dragon66

+0

@ dragon66 해쉬 함수가 좋은 경우 효율성은 모든 항목의 'O (1)'또는 전체 모음의 'O (N)'인 해시 테이블과 동일합니다. – dasblinkenlight

+0

dasblinkenlight : 루프 외부로 나가는 것을 알고 있지만 랩 오브젝트 생성에 대해 조금 걱정됩니다. – dragon66

-2

중복 된 내용이 포함 된 ArrayList을 반복하고 HashSet에 추가하십시오. HashSet에서 add 메소드가 false를 반환하면 콘솔에 복제본을 기록하십시오.

+1

OP가 말하기를, 그는 equals()를 사용할 수 없습니다. 'HashSet'은'hashCode()'와'equals()'를 사용합니다. 따라서 그는'HashSet'을 사용할 수 없습니다. –

0

TreeSet의 쉽게이 작업을 수행 할 수 있습니다 : 세트에 항목을 추가하고 항목이 고유 한 경우 true를 반환 uniqueItems.add(o)를 호출 할 때

Set uniqueItems = new TreeSet<>(yourComparator); 
List<?> duplicates = objects.stream().filter(o -> !uniqueItems.add(o)).collect(Collectors.toList()); 

yourComarator 사용됩니다. 비교자가 항목을 중복으로 간주하면 add(o)은 false를 반환합니다.

이 항목의 equals 메서드는 the TreeSet documentation에 따라 yourComarator과 일치해야합니다.