6

我的代码中有一个场景,我需要比较两个列表并从第一个列表中删除第二个列表中存在的对象。类似于 List 的“removeAll”对象的工作方式。由于我的 List 是在自定义对象上创建的,因此 removeAll 方法对我不起作用。

我已经尝试了各种方法来完成这项工作: - 为包含列表的自定义对象实现了 equals() 和 hashCode - 为自定义对象实现了 Comparable 接口 - 为自定义对象实现了 Comparator 接口

我什至尝试过使用 Apache Common 的 CollectionUtils 和 ListUtils 方法(减法、相交、removeAll)。似乎没有一个工作。

我知道我可能需要编写一些自定义删除代码。但不知道如何去做。任何帮助我朝着正确方向前进的指示都将不胜感激。

谢谢,杰

4

4 回答 4

14

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"

为了使这项工作,您存储的对象只需要正确实现 equals/hashCode 合约,即:给定任意两个对象ab

a.equals(b) == b.equals(a)

和:

a.hashCode() == b.hashCode() if a.equals(b)

不正确定义的 equals 和 hashCode 方法会创建未定义的行为,并且是集合相关问题的常见原因。

于 2010-04-11T14:40:06.960 回答
6

覆盖equalshashCode方法足以使方法removeAll在自定义对象上工作。

您可能没有以适当的方式覆盖它们。一些代码会对我们有很大帮助。

于 2010-04-11T14:44:09.700 回答
4

你说:

...由于我的 List 是在自定义对象上创建的,因此 removeAll 方法对我不起作用。

正如其他人所说, .removeAll() 应该适用于您描述的场景,即使对于自定义对象,只要自定义对象遵守 Java Collections 对其对象的期望,包括正确实现 equals() 和 hashCode()方法。

我已经尝试了各种方法来完成这项工作: - 为包含列表的自定义对象实现了 equals() 和 hashCode - 为自定义对象实现了 Comparable 接口 - 为自定义对象实现了 Comparator 接口......

听起来您正在尝试不同的方法:编码一个,尝试它,快速编码另一个,尝试它,编码另一个,......值得放慢速度并尝试了解每种方法失败和/或确定的原因为什么这种方法不适用于您的情况,然后再继续下一个。如果您已经调查并确定了每种方法不起作用的原因,请在您的问题中解释。如果你还没有,那么让我们通过发布代码来提供帮助。

既然大多数人都同意第一种方法 (.removeall()) 应该有效,并且由于涉及到自定义对象,为什么不快速回顾一下这个 StackOverflow 问题,看看是否有什么从你身上跳出来:

在 Java 中覆盖 equals 和 hashCode

“在 java 类中覆盖 equals 和 hashCode 时,我需要考虑哪些问题/陷阱?”

于 2010-04-11T15:20:50.440 回答
0

我发现他原来的说法是真的。仅当您覆盖迭代器中的删除时,removeAll 才会自动工作。仅仅覆盖 Collection 中的 remove 是不够的,因为 removeAll(以及 clear 和 retainAll)都使用迭代器来工作。由于在使用迭代器时不应更改底层集合,但迭代器中的 remove 除外,如果不覆盖迭代器中的 remove,removeAll、clear 和 retainAll 将不起作用。如果您在迭代器内的 remove 方法中抛出 UnsupportedOperationException,如果您调用所讨论的三种方法之一,您将看到这种情况。

于 2013-10-13T15:49:38.490 回答