2012-07-26 2 views
1

2 개의 사용자 정의 객체의 ArrayList가 있습니다. 두 ArrayList에서 중복 항목을 제거하고 싶습니다.Java ArrayList 두 목록에서 중복을 제거합니다.

개체에는 fName, lName 및 id라는 세 개의 필드가 있습니다. id가 여러 번 발생하면 두 목록에서 모두 제거하려고합니다.

어떻게하면됩니까?

두 목록을 병합하고 2 개의 중복 항목을 제거하는 것이 좋습니다.

답변

2

병합하려면 : 두 목록의 내용을지도에 간단히 복사하십시오. 그럼 당신은 더 이상 중복이없는 (그러나 당신은 당신의 실제 순서를 느슨하게) :

Map<Integer, MyObject> temp = new HashMap<Integer, MyObject>(); 
for (MyObject obj:firstList) { 
    temp.put(obj.getId(), obj); 
} 
for (MyObject obj:secondList) { 
    temp.put(obj.getId(), obj); 
} 
List<MyObject> result = new ArrayList<MyObject>(temp.values()); 
+0

그는 결합 목록을 단 하나가 아니라 두 목록에서 중복을 제거하려고합니다. –

+0

병합은 괜찮 았지만주의를 기울이지 않았습니다. 객체는 동일한 ID 만 갖고 있으면 "중복"됩니다. 그래서지도 더 나은 접근입니다 –

+0

고마워요 안드레아스, 그 작동 중대한 .... – John

1

을 수업이 equalshashCode 방법의 올바른 구현이있는 경우, 중복을 제거하기 위해 HashSet으로 목록을 켭니다. HashSet<T> 생성자는 Collection<T>을 허용하므로 잘 보내야합니다.

사용자 지정 비교 함수 (예 : id 만 비교)가 필요한 경우 TreeSet을 만들 때 사용자 지정 Comparator<T> 구현을 전달하십시오. 요약하면 두 개체의 id을 비교하는 비교기를 만들고이를 TreeSet 생성자로 전달합니다. 그런 다음 두 목록의 항목을이 집합에 추가하면 중복을 제거 할 수 있습니다. 다음과 같이하십시오 :

public class Test { 

    public static void main(String[] args) { 
     Person p1 = new Person("first", "id1"); 
     Person p2 = new Person("dummy", "id1"); // same id as above 
     Person p3 = new Person("second", "id2"); 
     Person p4 = new Person("third", "id1"); 
     List<Person> asList = Arrays.asList(p1, p2, p3, p4); 
     CustomComparator comparator = new CustomComparator(); 
     TreeSet<Person> ts = new TreeSet<Person>(comparator); 
     TreeSet<Person> duplicates = new TreeSet<Person>(comparator); 
     for (Person p : asList) { 
      if (ts.contains(p) || duplicates.contains(p)) { 
       duplicates.add(p); 
       ts.remove(p); 
      } else { 
       ts.add(p); 
      } 
     } 
     System.out.println(ts); 
    } 

} 

class Person { 

    public Person(String name, String id) { 
     super(); 
     this.name = name; 
     this.id = id; 
    } 

    public String name; 

    public String id; 

    @Override 
    public String toString() { 
     StringBuilder builder = new StringBuilder(); 
     builder.append("Person [id="); 
     builder.append(id); 
     builder.append(", name="); 
     builder.append(name); 
     builder.append("]"); 
     return builder.toString(); 
    } 

} 

class CustomComparator implements Comparator<Person> { 

    @Override 
    public int compare(Person o1, Person o2) { 
     return o1.id.compareTo(o2.id); 
    } 

} 
+0

사실 나는 이미 필드 fName ..에 따라 중복 제거 equals()를 재정의하고 있습니다 (즉, removeAll을 사용하여 목록 중 하나에서 공용 fName을 제거하십시오) ... 그러나 "id"필드의 경우 두 목록에서 모두 제거하고 싶습니다. 내가 어떻게 이것을 습득 할 수 있는지 확실하지 않니? – testndtv

+0

설명을 위해 샘플 스 니펫을 추가했습니다. –

+0

방금 ​​전 예를 들어 보았습니다 ... 복제 된 개체 중 하나가 제거되었습니다 ... 중복 된 개체를 모두 제거하고 싶습니다. 귀하의 예제에 따라, 결국, 그것은 단지 하나의 레코드 (ID2)를 반환해야합니다 ... – testndtv

0

Set을 사용하십시오.

참고 : 변경 가능한 개체가 설정된 요소로 사용되는 경우 큰주의가 필요합니다. 오브젝트가 세트의 요소 인 동안 equals 비교에 영향을주는 방식으로 오브젝트의 값이 변경되면 세트의 작동은 지정되지 않습니다. 이 금지의 특별한 경우는 세트가 자신을 요소로 포함하는 것이 허용되지 않는다는 것입니다.

0
HashSet<Integer> list_1_ids = new HashSet<Integer>(); 
HashSet<Integer> list_2_ids = new HashSet<Integer>(); 
for (CustomObject x : list1) list_1_ids.add(x.id); 
for (CustomObject x : list2) list_2_ids.add(x.id); 
HashSet<Integer> both_ids = list_1_ids; 
both_ids.retainAll(list_2_ids); 
List<CustomObject> pruned_list_1 = new ArrayList<CustomObject>(); 
for (CustomObject x : list1) if (!both_ids.contains(x.id)) pruned_list_1.add(x); 
List<CustomObject> pruned_list_2 = new ArrayList<CustomObject>(); 
for (CustomObject x : list2) if (!both_ids.contains(x.id)) pruned_list_2.add(x);