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

Wil*_*ner 7 java comparison arraylist

在开始之前,我认为这个问题有一个非常简单的答案,我只是忽略了.我想到了一些关于手头问题的眼睛能够很快指出我的问题.

我有两个我要比较的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");
Run Code Online (Sandbox Code Playgroud)

我的Person课很简单,只为这个例子创建

public class Person {
    private String name;

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

    public String getName() {
        return name;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

因此ArrayList,一旦比较完成,我希望结果中包含以下信息

contactList           //removed Person
    - Rob

updatedContactList    //new Person
    - Phil
Run Code Online (Sandbox Code Playgroud)

这是我放在一起的代码

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));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

我意识到我可能深度克隆更新ArrayList并只是从那个删除对象,但我想知道是否有一种方法,而不必克隆它.

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

Mar*_*nik 7

你真正拥有的不是列表,而是集合:将旧的和新的联系人建模为Set.同时实施equalshashCode为您的Person班级确保正确操作.

一旦你有了,你将能够编写单行来计算设置差异(这是你需要的):

final Set<Person> contactsBackup = new HashSet<>(contacts);
contacts.removeAll(updatedContacts);
updatedContacts.removeAll(contactsBackup);
Run Code Online (Sandbox Code Playgroud)

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

如果,由于某种原因对我来说根本不明显,你真的需要列表,相同的代码也适用于它们(List也定义removeAll),但是你必须忍受O(n 2)复杂性这个操作需要列表.