2013-06-03 25 views
6

Prima di iniziare, penso che questa domanda abbia una risposta molto semplice a cui sto semplicemente guardando. Ho pensato che qualche altro sguardo sulla domanda in questione sarà in grado di evidenziare il mio problema abbastanza velocemente.Come rimuovere oggetti duplicati da due elenchi di array distinti?

Ho due elenchi di array che voglio confrontare e rimuovere i duplicati da ciascuno di essi. Il primo ArrayList è un ArrayList di informazioni precedenti in cui il secondo ArrayList contiene le nuove informazioni.

Come così

ArrayList<Person> contactList = new ArrayList(); 
contactList.add(new Person("Bob"); 
contactList.add(new Person("Jake"); 
contactList.add(new Person("Joe"); 
ontactList.add(new Person("Rob"); 

ArrayList<Person> updatedContactList = new ArrayList(); 
updatedContactList.add(new Person("Bob"); 
updatedContactList.add(new Person("Jake"); 
updatedContactList.add(new Person("Joe"); 
updatedContactList.add(new Person("Phil"); 

La mia classe Person è molto semplice, creato esclusivamente per questo esempio

public class Person { 
    private String name; 

    public Person(String a_name) { 
     name = a_name; 
    } 

    public String getName() { 
     return name; 
    } 
} 

Quindi, utilizzando gli esempi di cui sopra, voglio rimuovere tutti i duplicati. Sto tentando di mantenere solo le due liste di array, se possibile, ma sono disposto a fare un clone profondo di una delle liste di array, se necessario.

quindi voglio il conseguente ArrayList di avere le seguenti informazioni in esso una volta che il confronto è fatto

Ecco il codice che ho messo insieme

for(int i = 0; i < contactList.size(); i++) { 
    for(int j = 0; j < updatedContactList.size(); j++) { 

     if(contactList.get(i).getName().equals(updatedContactList.get(j).getName())) { 
      //removed friends      
      contactList.remove(contactList.get(i)); 

      //new friends ---- only one at a time works 
      //updatedContactList.remove(updatedContactList.get(j)); 
     } 
    } 
} 

Sono solo in grado per rimuovere una persona da una delle liste array nel ciclo precedente altrimenti ottengo risultati errati.

Quindi la mia domanda è, c'è un modo semplice per rimuovere gli elementi duplicati da entrambe le liste di array? Se è così, come faccio a farlo.

Mi rendo conto che probabilmente ho potuto clonare in profondità l'aggiornato ArrayList e rimuovere solo gli oggetti da quello, ma mi chiedo se c'è un modo senza doverlo clonare.

Mi rendo anche conto che potrei semplicemente inserire tutti gli elementi in un Set e rimuovere i duplicati, ma voglio mantenere separati gli oggetti "rimossi" e "nuovi" Person.

+0

Suppongo che le singole liste non abbiano duplicati, corretto? – arshajii

+0

@arshajii Una volta eseguito il confronto, ogni elenco non deve contenere duplicati tra i due. Un ArrayList conterrà il 'Person' (s) rimosso e l'altro ArrayList conterrà solo nuovi oggetti' Person'. – WilliamShatner

+0

Intendo prima mano, prima che venga fatto qualcosa ai due elenchi. Ad esempio, non puoi avere due 'Bob' in' contactList', giusto? – arshajii

risposta

6

Cosa hai davvero non è liste, ma insiemi: il modello sia la vecchia e la nuova contatti come Set. Implementare anche equals e hashCode per la classe Person per garantire il corretto funzionamento.

Una volta che avete, sarete in grado di scrivere battute per calcolare le differenze set (che è quello che serve):

final Set<Person> contactsBackup = new HashSet<>(contacts); 
contacts.removeAll(updatedContacts); 
updatedContacts.removeAll(contactsBackup); 

Si noti che questa consiste nel fare una copia più, ma non è una copia profonda — vengono copiati solo i riferimenti. Questa è un'operazione molto leggera e non dovresti preoccuparti del suo impatto.

Se, per qualche motivo non è affatto ovvio per me, si ha realmente bisogno liste, lo stesso codice funzionerà anche per loro (List definisce anche removeAll), ma si dovrà convivere con O (n complessità che questa operazione comporta per le liste.

+0

+1. Il runtime di 'List # removeAll (Collection)' dipende in realtà dal tipo di collezione passato come parametro. La tua affermazione è vera per 'list.removeAll (otherList);'. Di seguito sarebbe la lista 'O (n)': '.removeAll (hashset); ' – jlordo

+0

@MarkoTopolnik Questo sembra un modo semplice e semplice per farlo (come fa il metodo di jLordo), ma cosa succede se voglio che le mie liste siano ordinate? Ad esempio, quando li analizzo dall'xml vengono in ordine alfabetico. Ma se poi deciderò di volere che siano ordinati in base a qualche informazione diversa, sarà un problema una volta che saranno un set? – WilliamShatner

+0

@jlordo Beh, non mi sono affatto opposto alla tua affermazione :) Ma ho notato un errore nel mio commento, quindi l'ho cancellato. Non riuscivo a mantenere il codice alla lettera. –

3

Override equals() e hashCode() nella tua classe Person e semplicemente fanno:

Set<Person> temp = new HashSet<>(contactList); 
contactList.removeAll(updatedContactList); 
updatedContactList.removeAll(temp); 
temp.clear(); // not necessary if this code is in a method 
+1

Puoi approfondire un po '? Presumo per 'equals()' Vorrei fare ciò che ho fatto sopra (correggimi se sbaglio). Non ho mai sovrascritto 'hashCode()' prima. Cosa farei nel mio metodo 'hashCode()' sovrascritto? – WilliamShatner

+1

Stai usando eclissi? In tal caso, fai clic su Origine -> Genera hashCode() ed equals() ' – jlordo

+0

Netbeans 7.1 (jdk è ancora a 6) – WilliamShatner

1

In questo caso uso Set e non List (questo è usato se hai trovato i dati da DB usando Hibernate esempio), se possibile. Quindi puoi eseguire l'override dei metodi equals e hashcode nella classe person in modo che, aggiungendo i confronti richiesti, possano essere fatti e duplicati possano essere eliminati. LinkedHashSet può essere usato come Liste può diventare lento man mano che i dati crescono.

0

Si tratta di un'una linea elegante soluzione facendo uso delle Java 8 capacità

public static final <T> void removeCommonEntries(Collection<T> a, Collection<T> b){ 
     b.removeIf(i -> a.remove(i)); 
} 

ho messo questa soluzione nella vostra abitudine CollectionUtils.

Problemi correlati