Поиск дубликатов в коллекции



Как лучше всего найти и отметить повторяющиеся объекты в коллекции? Допустим, у нас есть список лиц, и наша дублирующая стратегия основана на точном совпадении имени и фамилии.




  1. идентифицировать все дубликаты

  2. отметьте каждого дубликата человека, указывая, что это дубликат

  3. для каждого дубликата человека определите объект, который является дубликатом


Есть ли простой способ сделать это с гуавой?
546   4  

4 ответов:

Для этого Вам не нужна гуава:

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);
  }
}
Тем не менее, вы можете использовать гуаву Table вместо Map и избежать необходимости создавать Name... например, используйте имя в качестве ключей строк, а фамилию-в качестве ключей столбцов. Другой вариант-использовать Multimaps.index для индексации всех людей в вашем списке по именам. Тогда для каждого списка людей, сопоставленного с определенным именем, первым человеком будет первый человек с этим именем из вашего списка, а остальные будут дубликатами.

Вы можете попробовать использовать TreeMultimap гуавы.

Создайте новый TreeMultimap, инициализируя его с помощью компаратора для сравнения ваших людей, как вам нравится: TreeMultimap.создать (компаратор, упорядочивание.произвольно())

Вот модульный тест:

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

}

Почему бы не попробовать переопределить .equals () в объекте person. Затем добавьте новое поле для каждого объекта person 'duplicateOf' или что-то еще.

Затем просто пройдите по массиву, сверяя каждого человека с другими. Если поле persons 'duplicateOf' равно null, пропустите его. Если.equals() возвращает true вы можете установить поле 'duplicateOf'.

Человек класса должен реализовать 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].

Comments

    Ничего не найдено.