如何从两个单独的ArrayLists中删除重复的对象?

时间:2013-06-03 18:43:37

标签: java arraylist comparison

在开始之前,我认为这个问题有一个非常简单的答案,我只是忽略了。我想在眼前的问题上可以更快地指出我的问题。

我有两个我要比较的ArrayLists,并从每个ArrayLists中删除重复项。第一个ArrayListArrayList旧信息,而第二个ArrayList包含新信息。

喜欢这样

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");

我的Person类非常简单,仅为此示例创建

public class Person {
    private String name;

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

    public String getName() {
        return name;
    }
}

因此,使用上面的示例,我想删除所有重复项。如果可能的话,我正在尝试将它保留到两个ArrayLists中,但如果必须的话,我愿意深入克隆其中一个ArrayLists。

所以我希望生成的ArrayList在完成比较后会在其中包含以下信息

contactList           //removed Person
    - Rob

updatedContactList    //new Person
    - Phil

以下是我放在一起的代码

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

我只能从上面循环中的一个ArrayLists中删除Person,否则会得到不正确的结果。

所以我的问题是,是否有一种简单的方法可以从两个ArrayLists中删除重复的元素?如果是这样,我该怎么做呢。

我意识到我可以深度克隆更新后的ArrayList,只是删除那个中的对象,但我想知道是否有一种方法而不必克隆它。

我也意识到我可以将所有元素填充到一个Set中,它会删除重复项,但我想将'删除'和'新'Person对象分开。

5 个答案:

答案 0 :(得分:7)

您真正拥有的不是列表,而是集合:将旧联系人和新联系人建模为Set。同时为equals课程实施hashCodePerson,以确保正常运作。

一旦你有了这个,你就可以编写单行来计算设定差异(这就是你需要的):

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

请注意,这涉及再创建一个副本,但不是复制的只有深拷贝的引用。这是一个非常轻量级的操作,你不应该担心它的影响。

如果由于某些原因对我来说根本不明显,你真的需要列表,同样的代码也适合他们(List也定义removeAll),但你必须要活着对于O(n 2 )复杂度,此操作需要列表。

答案 1 :(得分:3)

equals()课程中覆盖hashCode()Person,然后执行以下操作:

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

答案 2 :(得分:2)

Set

创建addAllArrayLists
Set<Person> set = new ArrayList<Person>();

http://docs.oracle.com/javase/6/docs/api/java/util/Set.html

答案 3 :(得分:1)

在这种情况下,使用Set而不是List(如果可能的话,如果你使用说Hibernate从DB获取数据,则使用它)。然后,您可以在person类中覆盖equals和hashcode方法,以便在添加所需的比较时可以进行并且可以取出重复项。可以使用LinkedHashSet,因为随着数据的增长,列表会变慢。

答案 4 :(得分:0)

这是一个利用Java 8功能的一线优雅解决方案

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

我将此解决方案放入您的自定义CollectionUtils