【问题标题】:Problem with implementing removeAll for List of custom object为自定义对象列表实现 removeAll 的问题
【发布时间】:2011-02-06 17:23:10
【问题描述】:

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

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

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

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

谢谢, 周杰伦

【问题讨论】:

  • 首先,给出一些代码,这样我们就不会猜测了
  • 我认为如果你能展示你正在尝试做的事情的代码,这个问题可能会更清楚。
  • 这里和下面都有建议,但具体请发布您的 equalshashCode 方法的代码。您可能尝试过这些,但写错了。这是正确的方法,如果操作正确,将与 removeAll() 一起使用。

标签: java list removeall


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    你说:

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

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

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

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

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

    Overriding equals and hashCode in Java

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

    【讨论】:

      【解决方案3】:

      Java 集合已经满足您的方案。调用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 方法会产生未定义的行为,并且是集合相关问题的常见原因。

      【讨论】:

      • @Cletus:他实际上说(在下面一点)他尝试过但对他没有用。
      • @Roman 直到他发布一些我不相信的代码。很可能会归结为 API 使用不当或违反 equals/hashCode 合约等。
      • 这肯定是我的问题。重新生成 equals 和 hashCode 然后事情又开始工作了。谢谢:-)
      【解决方案4】:

      重写equalshashCode 方法足以使removeAll 方法适用于自定义对象。

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

      【讨论】:

      • 请详细点?
      猜你喜欢
      • 1970-01-01
      • 2015-09-07
      • 2016-07-08
      • 1970-01-01
      • 2021-07-29
      • 1970-01-01
      • 1970-01-01
      • 2011-06-30
      • 1970-01-01
      相关资源
      最近更新 更多