【问题标题】:Best way to merge and remove duplicates from multiple lists in Java从 Java 中的多个列表中合并和删除重复项的最佳方法
【发布时间】:2013-05-03 10:13:28
【问题描述】:

我有一种情况,我将收到 2+ ArrayList<Widget> 并且我需要能够合并所有列表并删除任何重复的 Widget 以便我最终只得到 1 个包含所有 @ 的 ArrayList<Widget> 987654324@s 来自所有合并列表,但没有任何重复。

假设Widget 有一个重写的equals 方法可以用于确定两个Widgets 是否重复,尽管可能有更好的方法:

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

寻找实现这一目标的算法效率最高的方法。我很高兴使用 Apache Commons 或任何其他可以帮助我的开源库!提前致谢!

【问题讨论】:

    标签: java performance algorithm list merge


    【解决方案1】:

    对于每个ArrayList&lt;Widget&gt;,使用addAll 将每个元素添加到Set&lt;Widget&gt;HashSetTreeSet,取决于它们是否可以以某种方式排序或可散列)。默认情况下,集合不包含重复项。

    如果最后需要,您可以将此 Set 转换回 (Array)List

    请注意,如果您决定使用HashSet,则需要为您的Widget 类实现hashCode,但如果您有一个覆盖的equals,,则无论如何都应该这样做。

    编辑:这是一个例子:

    //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 但不想在您的 Widget 类上实现 Comparable&lt;T&gt;,您可以给集合本身一个 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());
                }
               });
    

    【讨论】:

    • 哇,谢谢@Yuushi (+1) - 如果我尝试向集合中添加一个骗子,我会得到运行时异常吗?或者Java会忽略添加的欺骗(这是我想要的)。再次感谢!
    • Java 将忽略添加的重复项
    • @IAmYourFaja 它只会忽略欺骗。
    • 假设每个列表在数学上已经是一个集合,使用 Set.addAll 而不是一次老化一个元素会更快。
    • @Yuushi 具有相同哈希码的两个项目被认为可能相等。 Set 仍然会在哈希匹配后调用 equals 来检查项目是否实际上相同!
    【解决方案2】:

    我会这样做

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

    【讨论】:

    • 感谢@Evgeniy (+1) - 请在上面的 Yuushi 回答中查看我对 Yuushi 的最后一个问题 - 我有同样的问题要问你!
    • 由于我们使用的是设置重复项,因此不会添加。不会有例外
    【解决方案3】:

    使用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 中删除所有重复值。

    【讨论】:

    • 感谢@buptcoder (+1) - 请在上面的回答中查看我对 Yuushi 的最后一个问题 - 我也有同样的问题要问你!
    猜你喜欢
    • 2015-11-02
    • 2018-03-13
    • 1970-01-01
    • 2020-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-25
    相关资源
    最近更新 更多