2013-05-09 12 views
9

Mam sytuację, w której będę otrzymywać 2+ ArrayList<Widget> i muszę mieć możliwość scalenia wszystkich list i usunięcia dowolnego duplikatu Widget, tak, żebym zakończył tylko 1 ArrayList<Widget>, który zawiera wszystkie Widget s ze wszystkich scalonych list, ale bez żadnych duplikatów.Najlepszy sposób na scalanie i usuwanie duplikatów z wielu list w Javie

Załóżmy Widget ma nadpisane equals metodę może być używany do określania, czy dwa Widget S są duplikaty, chociaż nie może być lepszy sposób:

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

Szukasz najbardziej algorytmicznie efektywnego sposobu realizacji to. Cieszę się, że mogę korzystać z Apache Commons lub innych bibliotek open source, które również mogłyby mi pomóc! Z góry dziękuję!

Odpowiedz

11

Dla każdego ArrayList<Widget>, dodać każdy element do Set<Widget> (HashSet lub TreeSet, w zależności od tego, czy można je zamówić w jakiś sposób, czy są hashable) wykorzystując addAll. Zestawy domyślnie nie zawierają duplikatów.

Możesz przekonwertować ten Set z powrotem na (Array)List, jeśli chcesz na końcu.

Uwaga trzeba będzie wdrożyć hashCode dla swojej klasy Widget jeśli zdecydujesz się użyć HashSet, ale jeśli masz nadpisane equals, należy to zrobić tak.

Edycja: Oto przykład:

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

Jeśli chcesz użyć TreeSet ale nie chcą wdrożyć Comparable<T> na swojej klasie Widget można dać sama ustawić Comparator obiektu:

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 dzięki @Yuushi (+1) - będę się wyjątek czasu wykonywania, gdy próbuję dodać duplikatem do zestawu? A może Java po prostu zignoruje dodane duplikaty (tego właśnie chcę). Dzięki jeszcze raz! – IAmYourFaja

+0

Java po prostu zignoruje dodany duplikat –

+1

@IAmYourFaja Po prostu zignoruje duplikat. – Yuushi

2

Zastosowanie Set Collection Klasa,

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; 

Teraz tutaj Set usunie wszystkie duplikaty wartości z ArrayList.

+0

Dzięki @buptcoder (+1) - proszę zobaczyć moje ostatnie pytanie do Yuushi w jego/jej odpowiedzi abov e - Mam dla ciebie takie samo pytanie! – IAmYourFaja

8

chciałbym zrobić to w ten sposób

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

Dzięki @Evgeniy (+1) - proszę zobaczyć moje ostatnie pytanie do Yuushi w jego/jej odpowiedzi powyżej - Mam to samo pytanie dla ciebie! – IAmYourFaja

+0

Ponieważ używamy Ustaw duplikaty nie zostaną dodane. Nie będzie wyjątków –

Powiązane problemy