2011-11-12 11 views
5

Qual è il modo migliore per trovare e contrassegnare gli oggetti duplicati in una raccolta? Diciamo che abbiamo una lista persone e la nostra strategia duplicata si basa sulla corrispondenza esatta di nome e cognome.Ricerca di duplicati in una raccolta

  1. Identificare tutti i duplicati
  2. Mark ogni persona duplicato indica che è un duplicato
  3. Per ogni persona in duplicato, identificare l'oggetto è il duplicato di

C'è un modo semplice di fare questo con guava?

+0

Puoi chiarire cosa si intende "identificare l'oggetto è è il duplicato di "- presumo tu intendi che il primo elemento è l'elemento" reale "e gli elementi successivi sono duplicati? –

risposta

5

Non è necessario Guava di fare questo:

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

Detto questo, si potrebbe utilizzare un Guava Table invece di un Map e di evitare la necessità di creare il Name ... utilizzare il nome come la riga chiavi e cognome come tasti di colonna, per esempio.

Un'altra scelta potrebbe essere quella di utilizzare Multimaps.index per indicizzare tutte le persone nell'elenco per nome. Quindi per ogni elenco di persone associate a un nome particolare, la prima persona sarebbe la prima persona con quel nome dall'elenco e le altre sarebbero duplicate.

1

Perché non provare a sovrascrivere .equals() nell'oggetto persona. Quindi aggiungi un nuovo campo all'oggetto di ciascuna persona "duplicateOf" o qualcosa.

Quindi basta fare un ciclo sull'array, controllando ogni persona contro gli altri. Se il campo "duplicateOf" delle persone è nullo, saltalo. Se .equals() restituisce true, puoi impostare il campo 'duplicateOf'.

1

La classe Persona deve implementare il boolean equals(Object o).

Quindi è possibile trovare i duplicati in questo modo:

Hai qualche parte: 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; 
    } 
} 

Ora avete l'Array duplicateOf che potete leggere in questo modo: Il duplicato di elemento j è all'indice duplicateOf[j].

2

Si può provare a utilizzare Guava's TreeMultimap.

Creare una nuova TreeMultimap inizializzandolo con un comparatore per il confronto voi persone come volete: TreeMultimap.create(Comparator, Ordering.arbitrary())

Ecco una prova di unità:

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

Come posso soddisfare il requisito n. 3 dalla mia domanda? –

+0

La risposta è stata aggiornata. Ci scusiamo per ingannarti con i multiset. Si prega di provare a utilizzare TreeMultimaps. – szhem

+2

L'uso di una multimappa ordinata non è necessario e rende il tuo intento meno chiaro dal momento che lo stai usando solo come metodo per scegliere un'eguaglianza chiave diversa. È preferibile utilizzare il nome stesso come chiave. Quindi puoi semplicemente usare 'Multimaps.index'. – ColinD

Problemi correlati