为自定义对象列表实现removeAll的问题

时间:2010-04-11 14:36:10

标签: java list removeall

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

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

我甚至尝试过使用Apache Common的CollectionUtils和ListUtils方法(减去,交叉,删除所有)。似乎没有用。

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

谢谢, 杰

4 个答案:

答案 0 :(得分: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方法会创建未定义的行为,并且是集合相关问题的常见原因。

答案 1 :(得分:6)

覆盖equalshashCode方法足以使方法removeAll处理自定义对象。

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

答案 2 :(得分:4)

你说:

  

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

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

  

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

这听起来像是你的枪击不同的方法:编码一个,尝试它,快速编码另一个,尝试它,编码另一个,...这是值得减速并试图理解为什么每个方法失败和/或确定为什么这种方法不适合您的情况,然后继续下一步。如果您已经调查并确定了为什么每种方法都不起作用,请在您的问题中解释。如果还没有,请通过发布代码告诉我们。

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

  

Overriding equals and hashCode in Java

     

“在java类中重写equals和hashCode时需要考虑哪些问题/陷阱?”

答案 3 :(得分:0)

我发现他原来的陈述是真的。只有在迭代器中覆盖remove时,removeAll才会自动运行。刚刚覆盖Collection中的remove是不够的,因为removeAll(和clear和retainAll)都使用迭代器来工作。由于除了迭代器中的remove之外,在使用迭代器时不应更改底层集合,如果不在迭代器中覆盖remove,则removeAll,clear和retainAll将不起作用。如果在迭代器内部的remove方法中抛出UnsupportedOperationException,那么如果调用所讨论的三种方法之一,就会看到这种情况。