在集合中查找重复项

时间:2011-11-12 22:53:29

标签: java guava

在集合中查找和标记重复对象的最佳方法是什么?假设我们有一个列表人员,我们的重复策略基于名字和姓氏的完全匹配。

  1. 识别所有重复项
  2. 标记每个重复的人,表明它是重复的
  3. 对于每个重复的人,确定它是
  4. 的副本

    使用番石榴有一种简单的方法吗?

4 个答案:

答案 0 :(得分:5)

你不需要Guava这样做:

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);
  }
}

也就是说,您可以使用Guava Table而不是Map,并避免需要创建Name ...使用第一个名称作为行键,将姓氏作为列钥匙,比方说。

另一种选择是使用Multimaps.index按名称索引列表中的所有人。然后,对于映射到特定名称的每个人员列表,第一个人将是列表中具有该名称的第一个人,其他人将是重复的。

答案 1 :(得分:2)

您可以尝试使用Guava's TreeMultimap

创建一个新的TreeMultimap,用比较器初始化它,根据需要比较你的人:TreeMultimap.create(Comparator, Ordering.arbitrary())

这是一个单元测试:

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());
    }

}

答案 2 :(得分:1)

为什么不尝试在person对象中覆盖.equals()。然后为每个人对象'duplicateOf'或其他东西添加一个新字段。

然后循环遍历数组,检查每个人与其他人。如果人员'duplicateOf'字段为空,则跳过它。如果.equals()返回true,则可以设置'duplicateOf'字段。

答案 3 :(得分:1)

类Person必须实现boolean equals(Object o)

然后你可以这样找到重复:

你有一个地方: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;
  }
}

现在您可以使用以下方式阅读的数组duplicateOf:元素j的副本位于索引duplicateOf[j]