2013-05-09 10 views
9

Ho una situazione in cui riceverò 2+ ArrayList<Widget> e devo essere in grado di unire tutti gli elenchi e rimuovere qualsiasi duplicato Widget in modo che venga visualizzato solo 1 ArrayList<Widget> che contiene tutti gli Widget da tutti gli elenchi uniti, ma senza duplicati.Il modo migliore per unire e rimuovere i duplicati da più elenchi in Java

assumere Widget ha un equals metodo ignorato che può essere utilizzato per determinare se due Widget s sono duplicati, anche se ci può essere un modo migliore:

public ArrayList<Widget> mergeAndRemoveDupes(ArrayList<Widget> widgets...) { 
    // ??? 
} 

cercando un modo più algoritmico efficace di realizzare Questo. Sono felice di usare Apache Commons o altre librerie open source che potrebbero aiutarmi anche io! Grazie in anticipo!

risposta

11

Per ogni ArrayList<Widget>, aggiungere ogni elemento ad un Set<Widget> (HashSet o TreeSet, a seconda che essi possono essere ordinati in qualche modo, o sono hashable) utilizzando addAll. Gli insiemi non contengono duplicati per impostazione predefinita.

È possibile convertire questo Set in uno (Array)List se è necessario alla fine.

Nota è necessario implementare hashCode per la classe Widget se si decide di utilizzare un HashSet, ma se avete un sovrascritto equals, si dovrebbe fare in ogni caso.

Edit: Ecco un esempio:

//Either the class itself needs to implement Comparable<T>, or a similar 
//Comparable instance needs to be passed into a TreeSet 
public class Widget implements Comparable<Widget> 
{ 
    private final String name; 
    private final int id; 

    Widget(String n, int i) 
    { 
     name = n; 
     id = i; 
    } 

    public String getName() 
    { 
     return name; 
    } 

    public int getId() 
    { 
     return id; 
    } 

    //Something like this already exists in your class 
    @Override 
    public boolean equals(Object o) 
    { 
     if(o != null && (o instanceof Widget)) { 
      return ((Widget)o).getName().equals(name) && 
        ((Widget)o).getId() == id; 
     } 
     return false; 
    } 

    //This is required for HashSet 
    //Note that if you override equals, you should override this 
    //as well. See: http://stackoverflow.com/questions/27581/overriding-equals-and-hashcode-in-java 
    @Override 
    public int hashCode() 
    { 
     return ((Integer)id).hashCode() + name.hashCode(); 
    } 

    //This is required for TreeSet 
    @Override 
    public int compareTo(Widget w) 
    { 
     if(id < w.getId()) return -1; 
     else if(id > w.getId()) return 1; 
     return name.compareTo(w.getName()); 
    } 

    @Override 
    public String toString() 
    { 
     return "Widget: " + name + ", id: " + id; 
    } 
} 

Se si desidera utilizzare un TreeSet, ma non si vuole implementare Comparable<T> sulla tua classe Widget, si può dare il set di per sé un oggetto Comparator:

private Set<Widget> treeSet; 
.... 
treeSet = new TreeSet<Widget>(new Comparator<Widget>() { 
      public int compare(Widget w1, Widget w2) 
      { 
       if(w1.getId() < w2.getId()) return -1; 
       else if(w1.getId() > w2.getId()) return 1; 
       return w1.getName().compareTo(w2.getName()); 
      } 
      }); 
+0

Wow grazie @Yuushi (+1) - otterrò un'eccezione di runtime se provo ad aggiungere una vittima al set? O Java ignorerà semplicemente il dupe aggiunto (che è quello che voglio). Grazie ancora! – IAmYourFaja

+0

Java ignorerà semplicemente il duplicato aggiunto –

+1

@IAmYourFaja Semplicemente ignorerà il duplicato. – Yuushi

2

Usa Set Class Collection,

ArrayList<Widget> mergeList = new ArrayList<widget>(); 
mergeList.addAll(widgets1); 
mergeList.addAll(widgets2); 
Set<Widget> set = new HashSet<Widget>(mergeList); 
ArrayList<Widget> mergeListWithoutDuplicates = new ArrayList<widget>(); 
mergeListWithoutDuplicates .addAll(set); 
return mergeListWithoutDuplicates; 

Ora qui Set rimuoverà tutti i valori duplicati dal tuo ArrayList.

+0

Grazie @buptcoder (+1) - vedere la mia ultima domanda a Yuushi nella sua risposta abov e - Ho la stessa domanda per te! – IAmYourFaja

8

vorrei farlo in questo modo

Set<Widget> set = new HashSet<>(list1); 
set.addAll(list2); 
List<Widget> mergeList = new ArrayList<>(set); 
+0

Grazie a @Evgeniy (+1) - vedi la mia ultima domanda a Yuushi nella sua risposta sopra - Ho la stessa domanda per te! – IAmYourFaja

+0

Dato che stiamo usando Set duplicati non saranno aggiunti. Non ci saranno eccezioni –

Problemi correlati