Лучший способ объединить и удалить дубликаты из нескольких списков в Java

у меня есть ситуация, когда я буду получать 2+ ArrayList<Widget> и мне нужно иметь возможность объединить все списки и удалить любой дубликат Widget Так что я получаю только 1 ArrayList<Widget>, который содержит все Widgets из всех объединенных списков, но без каких-либо дубликатов.

предположим Widget был переопределен equals метод can используется для определения, являются ли два Widgets являются дубликатами, хотя может быть лучше так:

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

просмотр для наиболее алгоритмически эффективного способа выполнения этого. Я рад использовать Apache Commons или любые другие библиотеки с открытым исходным кодом, которые тоже помогут мне! Заранее спасибо!

3 ответов


для каждого ArrayList<Widget> добавить каждый элемент Set<Widget> (HashSet или TreeSet, в зависимости от того, могут ли они быть заказаны каким-либо образом или хэшируются), используя addAll. По умолчанию наборы не содержат дубликатов.

вы можете преобразовать это Set обратно в (Array)List если вам нужно в конце.

Примечание вам нужно будет реализовать hashCode для Widget класс если вы решили использовать HashSet, но если у вас есть переопределенный equals, вы должны сделать это в любом случае.

Edit: вот пример:

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

если вы хотите использовать TreeSet но не хочу, чтобы реализовать Comparable<T> на Widget класс, вы можете дать самому набору


Я бы сделал это так

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

использовать Set Коллекция Класс

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;

теперь здесь Set удалит все значения дубликатов из вашего ArrayList.