2011-11-12 41 views
5

Cách tốt nhất để tìm và đánh dấu các đối tượng trùng lặp trong Bộ sưu tập là gì? Hãy để chúng tôi nói rằng chúng tôi có một người Danh sách và chiến lược trùng lặp của chúng tôi dựa trên kết hợp chính xác của tên và họ.Tìm bản sao trong bộ sưu tập

  1. Xác định tất cả bản sao
  2. Đánh dấu mỗi người trùng lặp cho thấy nó là một bản sao
  3. Đối với mỗi người trùng lặp, xác định các đối tượng nó là bản sao của

Có cách nào đơn giản để làm điều này với ổi?

+0

Bạn có thể làm rõ những gì bạn có nghĩa là "xác định các đối tượng nó là bản sao của "- Tôi đoán bạn có nghĩa là mục đầu tiên là mục" thực ", và các mục tiếp theo là bản sao? –

Trả lời

5

Bạn không cần ổi để làm điều này:

List<Person> people = ... 
Map<Name, Person> peopleByName = new HashMap<>(); 
for (Person person : people) { 
    // Name is a simple value class with equality based on its fields 
    Name name = new Name(person.getFirstName(), person.getLastName()); 
    Person firstPersonWithName = peopleByName.get(name); 
    if (firstPersonWithName == null) { 
    peopleByName.put(name, person); 
    } else { 
    // or whatever you do to mark a duplicate 
    person.setDuplicateOf(firstPersonWithName); 
    } 
} 

Điều đó nói rằng, bạn có thể sử dụng một Ổi Table thay vì một Map và tránh cần để tạo ra các Name ... sử dụng tên đầu tiên như hàng chìa khóa và họ là chìa khóa cột.

Một lựa chọn khác là sử dụng Multimaps.index để lập chỉ mục tất cả những người trong danh sách của bạn theo tên. Sau đó, đối với mỗi danh sách những người được ánh xạ tới một tên cụ thể, người đầu tiên sẽ là người đầu tiên có tên đó từ danh sách của bạn và những người khác sẽ trùng lặp.

1

Tại sao không thử ghi đè .equals() trong đối tượng người. Sau đó, thêm một trường mới cho mỗi đối tượng người 'duplicateOf' hoặc một cái gì đó.

Sau đó, chỉ lặp qua mảng, kiểm tra từng người với những người khác. Nếu trường 'duplicateOf' của người đó bỏ qua nó. Nếu .equals() trả về true bạn có thể thiết lập trường 'duplicateOf'.

1

Lớp học Người phải triển khai boolean equals(Object o).

Sau đó, bạn có thể tìm thấy bản sao theo cách này:

Bạn có ở đâu đó: Collection<Person> list;

Person[] persons = list.toArray(); 
Integer[] duplicateOf = new Integer[persons.length]; 
Arrays.fill(duplicateOf, -1); 

// For all the values in the Collection 
for (int i = 0; i < persons.length; i++) { 

    // Find the duplicate 
    for (int j = 0; j < persons.length; j++) { 
    if (persons[i].equals(persons[j]) && i != j) 
     duplicateOf[j] = i; 
    } 
} 

Bây giờ bạn có mảng duplicateOf mà bạn có thể đọc theo cách này: Các bản sao của một yếu tố j là chỉ số duplicateOf[j].

2

Bạn có thể thử sử dụng Guava's TreeMultimap.

Tạo một TreeMultimap mới khởi tạo nó với một so sánh để so sánh các bạn những người như bạn muốn: TreeMultimap.create(Comparator, Ordering.arbitrary())

Dưới đây là một thử nghiệm đơn vị:

package org.test.guava; 

import java.util.Arrays; 
import java.util.Comparator; 
import java.util.List; 

import org.junit.Test; 

import com.google.common.collect.Multimap; 
import com.google.common.collect.Ordering; 
import com.google.common.collect.TreeMultimap; 

public class GuavaTest { 

    private static class Person { 
     private String name; 

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

     public String getName() { 
      return name; 
     } 

     @Override 
     public String toString() { 
      return "Person [name=" + name + "]"; 
     } 

    } 

    @Test 
    public void test() throws Exception { 
     List<Person> persons = Arrays.asList(new Person("person1"), new Person("person2"), new Person("person1")); 
     Comparator<Person> comparator = new Comparator<Person>() { 
      public int compare(Person o1, Person o2) { 
       return o1.getName().compareTo(o2.getName()); 
      } 
     }; 

     Multimap<Person, Person> groups = TreeMultimap.create(comparator, Ordering.arbitrary()); 
     for(Person person : persons) { 
      groups.put(person, person); 
     } 

     System.out.println(groups.asMap()); 
    } 

} 
+0

Làm cách nào tôi có thể đáp ứng yêu cầu # 3 từ câu hỏi của mình? –

+0

Câu trả lời được cập nhật. Xin lỗi vì đã gây nhầm lẫn cho bạn với nhiều lần. Hãy thử sử dụng TreeMultimaps. – szhem

+2

Sử dụng một multimap được sắp xếp là không cần thiết và nó làm cho ý định của bạn ít rõ ràng hơn vì bạn chỉ sử dụng bằng cách sử dụng nó như một cách để chọn một sự bình đẳng quan trọng khác. Sử dụng tên chính nó như là chìa khóa là thích hợp hơn. Sau đó, bạn chỉ có thể sử dụng 'Multimaps.index'. – ColinD

Các vấn đề liên quan