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
How do I remove duplicate objects from two separate ArrayLists?
提问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 ArrayList
is an ArrayList
of older information where as the second ArrayList
contains the new information.
我有两个 ArrayList,我想比较它们并从中删除重复项。第一个ArrayList
是ArrayList
旧信息,而第二个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 Person
class 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 ArrayList
to 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 ArrayList
and 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 equals
and hashCode
for your Person
class to ensure proper operation.
您真正拥有的不是列表,而是集合:将旧联系人和新联系人都建模为Set
. 还为您的班级实施equals
和以确保正确操作。hashCode
Person
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 (List
also 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 Person
class 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 Set
and addAll
from both the ArrayLists
.
创建Set
并addAll
从两个ArrayLists
。
Set<Person> set = new ArrayList<Person>();
回答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
.