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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16903633/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-01 00:20:22  来源:igfitidea点击:

How do I remove duplicate objects from two separate ArrayLists?

javaarraylistcomparison

提问by WilliamShatner

Before beginning, I think that this question has a very simple answer that I'm just overlooking. I figured a few more eyes on the question at hand will be able to point out my problem fairly quickly.

在开始之前,我认为这个问题有一个非常简单的答案,我只是忽略了。我想多看几眼手头的问题就能很快指出我的问题。

I have two ArrayLists that I want to compare and remove duplicates from each of them. The first ArrayListis an ArrayListof older information where as the second ArrayListcontains the new information.

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

Like so

像这样

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

My Personclass is very simple, created solely for this example

我的Person课程很简单,专门为这个例子创建的

public class Person {
    private String name;

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

    public String getName() {
        return name;
    }
}

So, using the above examples, I want to remove all duplicates. I'm trying keep it to just the two ArrayLists if possible, but am willing to do a deep clone of one of the ArrayLists if I have to.

因此,使用上面的示例,我想删除所有重复项。如果可能的话,我试图将它保留为两个 ArrayLists,但如果需要,我愿意对其中一个 ArrayLists 进行深度克隆。

So I want the resulting ArrayListto have the following information in it once the comparison is done

所以我希望结果ArrayList在比较完成后包含以下信息

contactList           //removed Person
    - Rob

updatedContactList    //new Person
    - Phil

Here is the code I've put together

这是我放在一起的代码

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

I'm only able to remove a Person from one of the ArrayLists in the above loop otherwise I get incorrect results.

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

So my question is, is there an easy way to remove the duplicated elements from both ArrayLists? If so, how do I go about it.

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

I realize that I could probably deep clone the updated ArrayListand just remove the objects from that one, but I'm wondering if there is a way without having to clone it.

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

I also realize that I could just stuff all the elements into a Set and it would remove the duplicates, but I want to keep the 'removed' and 'new' Person objects separate.

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

采纳答案by Marko Topolnik

What you really have is not lists, but sets: model both the old and the new contacts as a Set. Also implement equalsand hashCodefor your Personclass to ensure proper operation.

您真正拥有的不是列表,而是集合:将旧联系人和新联系人都建模为Set. 还为您的班级实施equals和以确保正确操作。hashCodePerson

Once you have that, you'll be able to write one-liners to calculate the set differences (which is what you need):

一旦你有了它,你就可以编写单行程序来计算集合差异(这是你需要的):

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

Note that this involves making one more copy, but it is not a deep copy—only references are copied. This is a very leightweight operation and you should not worry about its impact.

请注意,这涉及再制作一个副本,但它不是深度副本——仅复制引用。这是一个非常轻量级的操作,您不必担心它的影响。

If, for some reason not at all obvious to me, you really need lists, the same code will work for them, too (Listalso defines removeAll), but you will have to live with O(n2) complexity this operation entails for lists.

如果由于某种原因对我来说一点都不明显,你真的需要列表,同样的代码也适用于它们(List也定义了removeAll),但是你将不得不忍受这个操作对列表带来的O(n 2) 复杂性。

回答by jlordo

Override equals()and hashCode()in your Personclass and simply do:

覆盖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

回答by noMAD

Create a Setand addAllfrom both the ArrayLists.

创建SetaddAll从两个ArrayLists

Set<Person> set = new ArrayList<Person>();

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

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

回答by Harish Kumar

In this case use Set and not List (this is used if you are getting data from DB using say Hibernate) if possible. Then you can override equals and hashcode method in person class so that while adding required comparisons can be made and duplicates can be taken out. LinkedHashSet can be used as Lists can become slow as data in it grows.

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

回答by EliuX

This is a one line elegant solution making use of the Java 8 capabilities

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

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

I put this solution in your custom CollectionUtils.

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