java 为自定义对象列表实现 removeAll 的问题
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2617369/
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
Problem with implementing removeAll for List of custom object
提问by Jay
I have a scenario in my code where I need to compare two Lists and remove from the first list, objects which are present in the second list. Akin to how the "removeAll" object works for List. Since my List is created on a custom object, the removeAll method won't work for me.
我的代码中有一个场景,我需要比较两个列表并从第一个列表中删除第二个列表中存在的对象。类似于“removeAll”对象如何为 List 工作。由于我的 List 是在自定义对象上创建的,因此 removeAll 方法对我不起作用。
I have tried various methods to make this work: - implemented equals() and hashCode for the custom object comprising the list - implemented the Comparable Interface for the custom object - implemented the Comparator Interface for the custom object
我尝试了各种方法来完成这项工作: - 为包含列表的自定义对象实现了 equals() 和 hashCode - 为自定义对象实现了 Comparable 接口 - 为自定义对象实现了 Comparator 接口
I've even tried using the Apache Common's CollectionUtils and ListUtils methods (subtract, intersect, removeAll). None seem to work.
我什至尝试过使用 Apache Common 的 CollectionUtils 和 ListUtils 方法(相减、相交、removeAll)。没有一个似乎工作。
I understand I will perhaps need to write some custom removal code. But not sure how to go about doing that. Any pointers helping me move in the right direction will be really appreciated.
我知道我可能需要编写一些自定义删除代码。但不知道如何去做。任何帮助我朝着正确方向前进的指针将不胜感激。
Thanks, Jay
谢谢,杰
回答by cletus
Java Collections already cater for your scenario. Call Collection.removeAll(Collection)and it'll remove all the items from the passed in collection using the equals()method to test for equality.
Java Collections 已经可以满足您的需求。调用Collection.removeAll(Collection),它将使用equals()测试相等性的方法从传入的集合中删除所有项目。
List<String> list1 = new ArrayList<String>();
Collections.addAll(list1, "one", "two", "three", "four");
List<String> list2 = new ArrayList<String>();
Collections.addAll(list2, "three", "four", "five");
list1.removeAll(list2); // now contains "one", "two"
To make this work the objects you're storing just need to properly implement the equals/hashCode contract, which is: given any two objects aand b:
为了使这个工作,你存储的对象只需要正确实现 equals/hashCode 契约,即:给定任意两个对象a和b:
a.equals(b) == b.equals(a)
and:
和:
a.hashCode() == b.hashCode() if a.equals(b)
Improperly defined equals and hashCode methods create undefined behaviour and are the common cause of collections related issues.
不正确定义的 equals 和 hashCode 方法会产生未定义的行为,并且是集合相关问题的常见原因。
回答by Roman
Overriding equalsand hashCodemethods is enough to make method removeAllwork on custom objects.
覆盖equals和hashCode方法足以使方法removeAll在自定义对象上工作。
It's likely that you didn't override them in a proper way. Some code will help us a lot.
您可能没有以正确的方式覆盖它们。一些代码会对我们有很大帮助。
回答by Bert F
You said:
你说:
... Since my List is created on a custom object, the removeAll method won't work for me.
... 因为我的 List 是在自定义对象上创建的,所以 removeAll 方法对我不起作用。
As others have stated, .removeAll() should work for the scenario you described, even for custom objects, as long as the custom objects obey the contracts that Java Collections expects of its objects, including a properly implement equals() and hashCode() method.
正如其他人所说, .removeAll() 应该适用于您描述的场景,即使对于自定义对象,只要自定义对象遵守 Java 集合对其对象的期望,包括正确实现 equals() 和 hashCode()方法。
I have tried various methods to make this work: - implemented equals() and hashCode for the custom object comprising the list - implemented the Comparable Interface for the custom object - implemented the Comparator Interface for the custom object ...
我尝试了各种方法来完成这项工作: - 为包含列表的自定义对象实现了 equals() 和 hashCode - 为自定义对象实现了 Comparable 接口 - 为自定义对象实现了 Comparator 接口......
It sounds like your are shot-gunning different approaches: coding one, trying it, quickly coding another, trying it, coding yet another, ... It make be worthwhile to slow down and try to understand why each approach failed and/or determine why that approach won't work for your situation, before moving on to the next. If you've already investigated and determined why each approach won't work, please explain in your question. If you haven't, then let us help by posting code.
听起来您正在射击不同的方法:编码一种,尝试它,快速编码另一种,尝试它,编码另一种,......放慢速度并尝试理解为什么每种方法失败和/或确定是值得的为什么这种方法不适用于您的情况,然后再继续下一步。如果您已经调查并确定了为什么每种方法都不起作用,请在您的问题中进行解释。如果您还没有,那么让我们通过发布代码来提供帮助。
Since most people agree the first approach (.removeall()) should have work and since custom objects are involved, why not take a quick review of this StackOverflow question to see if anything jumps out of you:
由于大多数人都同意第一种方法 (.removeall()) 应该有效,并且由于涉及自定义对象,为什么不快速回顾一下这个 StackOverflow 问题,看看是否有任何问题:
Overriding equals and hashCode in Java
"What issues / pitfalls do I need to consider when overriding equals and hashCode in a java class?"
“在 Java 类中覆盖 equals 和 hashCode 时,我需要考虑哪些问题/陷阱?”
回答by sharonD
I have found that his original statement it true. removeAll works automatically only if you override the remove in the iterator. Just overriding the remove in the Collection is not enough because the removeAll (and clear and retainAll) all use the iterator to work. Since you should not change the underlying collection while using the iterator except for the remove in the iterator, if you do not override the remove in the iterator, the removeAll, clear and retainAll will not work. If you throw an UnsupportedOperationException in the remove method inside the iterator, that is what you will see if you call one of the three methods discussed.
我发现他原来的说法是真的。仅当您覆盖迭代器中的 remove 时,removeAll 才会自动工作。仅仅覆盖 Collection 中的 remove 是不够的,因为 removeAll(以及 clear 和 retainAll)都使用迭代器来工作。由于除了迭代器中的 remove 之外,您在使用迭代器时不应更改底层集合,如果您不覆盖迭代器中的 remove,则 removeAll、clear 和 retainAll 将不起作用。如果您在迭代器内的 remove 方法中抛出 UnsupportedOperationException,这就是您在调用所讨论的三个方法之一时将看到的结果。

