자바의 배열에서 복제물을 제거하는 가장 좋은 방법은 무엇입니까?

StackOverflow https://stackoverflow.com/questions/357421

  •  21-08-2019
  •  | 
  •  

문제

제거/필터링 된 복제물이 필요한 객체가 있습니다. 나는 객체 요소의 equals & hachcode를 무시하고 세트에 붙일 것입니다 ... 그러나 나는 다른 방법이 있는지, 아마도 다른 API의 영리한 방법이 있는지 확인하기 위해 적어도 폴링 스테이크 오버 플로우를해야한다고 생각했습니다.

도움이 되었습니까?

해결책

나는 당신의 접근 방식에 동의 할 것입니다 hashCode() 그리고 equals() 그리고 구현하는 것을 사용하십시오 Set.

이렇게하면 다른 개발자에게는 중개되지 않은 특성이 필요하다는 것을 분명히 알 수 있습니다.

또 다른 이유 - 당신은 지금 당신의 요구를 가장 잘 충족시키는 구현을 선택하게됩니다.

그리고 향후 구현을 변경하기 위해 코드를 변경할 필요가 없습니다.

다른 팁

웹에서 이것을 찾았습니다

다음은 Arraylist에서 복제물을 제거 할 수있는 두 가지 방법입니다. removedUplication은 removeduplicationwithoder에서 성능 오버 헤드로 순서를 유지하는 순서를 유지하지 않습니다.

  1. 제거 된 방법 :

    /** List order not maintained **/
    public static void removeDuplicate(ArrayList arlList)
    {
     HashSet h = new HashSet(arlList);
     arlList.clear();
     arlList.addAll(h);
    }
    
  2. 제거 된 방법 :

    /** List order maintained **/
    public static void removeDuplicateWithOrder(ArrayList arlList)
    {
       Set set = new HashSet();
       List newList = new ArrayList();
       for (Iterator iter = arlList.iterator(); iter.hasNext();) {
          Object element = iter.next();
          if (set.add(element))
             newList.add(element);
       }
       arlList.clear();
       arlList.addAll(newList);
    }
    

우선 equals 그리고 hashCode 그리고 세트를 만드는 것도 나의 첫 번째 생각이었습니다. 상속 계층에 어쨌든 이러한 방법의 재정의 버전을 갖는 것이 좋습니다.

생각한다 당신이 사용하는 경우 a LinkedHashSet 당신은 독특한 요소의 질서를 보존 할 것입니다 ...

기본적으로, 당신은 a를 원합니다 LinkedHashSet<T> 지원하는 구현 List<T> 임의의 액세스를위한 인터페이스. 따라서 이것이 필요한 것입니다.

public class LinkedHashSetList<T> extends LinkedHashSet<T> implements List<T> {

// Implementations for List<T> methods here ...

}

의 구현 List<T> 방법은 기본에 액세스하고 조작 할 수 있습니다 LinkedHashSet<T>. 비결은이 클래스가 List<T> 메소드 추가 (예외를 던지거나 다른 색인에서 항목을 다시 구하는 것은 옵션입니다. 이것은 클래스 사용자가 하나를 선택하거나 구성 할 수 있습니다).

목록을 사용하십시오 distinctList 요소를 처음으로 기록합니다 iterator 그것에 걸려 넘어져서 모든 복제물을 제거함에 따라 고정 목록을 반환합니다.

 private List removeDups(List list) {
        Set tempSet = new HashSet();
        List distinctList = new ArrayList();
        for(Iterator  it = list.iterator(); it.hasNext();) {
            Object next = it.next();
            if(tempSet.add(next)) {
                distinctList.add(next);
            } 
        }
        return distinctList;
   } 

Jason이 작성한 요점을 다음 의견으로 반복하고 싶습니다.

왜 그 시점에 자신을 배치합니까?

복제를 전혀 유지해서는 안되는 데이터 구조에 배열을 사용하는 이유는 무엇입니까?

a Set 또는 a SortedSet (요소가 자연 순서도있을 때) 요소를 항상 고정시키기 위해 항상. 삽입 순서를 유지 해야하는 경우 LinkedHashSet 지적한대로.

일부 데이터 구조는 종종 다른 데이터 구조를 선택해야한다는 힌트입니다.

물론 원래 게시물은 "처음에 복제 된 항목을 포함 할 수있는 배열을 어떻게 얻었습니까?"라는 질문을 제기합니다.

다른 목적으로 배열 (복제)가 필요합니까, 아니면 처음부터 세트를 사용할 수 있습니까?

또는 각 값의 발생 수를 알아야하는 경우 Map<CustomObject, Integer> 카운트를 추적합니다. 또한, Google 컬렉션 멀티 맵 클래스의 정의가 사용될 수 있습니다.

Set 확실히 당신의 최선의 방법입니다. 배열에서 물건을 제거하는 유일한 방법 (새 제품을 만들지 않고)은 그들을 무효화하고 나중에 많은 널 체크로 끝납니다.

일반적인 프로그래밍 표준에서 말하면 항상 컬렉션을 두 배로 열거 한 다음 소스와 대상을 비교할 수 있습니다.

그리고 내면의 열거가 소스 이후에 항상 한 항목을 시작하면 상당히 효율적입니다 (Pseudo 코드를 따라야합니다)

foreach ( array as source )
{
    // keep track where we are in the array
    place++;
    // loop the array starting at the entry AFTER the current one we are comparing to
    for ( i=place+1; i < max(array); i++ )
    {
        if ( source === array[place] )
        {
            destroy(array[i]);
        }
    }
}

당신은 아마도 휴식을 추가 할 수 있습니다. 파괴 후 진술이지만 첫 번째 복제본 만 발견하지만, 그것이 당신이 가질 전부라면, 그것은 작은 작은 최적화가 될 것입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top