【问题标题】:Using multiple alternatives of hashCode() and equals() for sets对集合使用 hashCode() 和 equals() 的多种替代方案
【发布时间】:2013-06-12 05:29:32
【问题描述】:

假设我有一个简单的 POJO 类 Class1 ,它有 2 个 int 类型的字段。

我已经实现了它的hashCode() 和equals() 方法来处理这两个字段,以便将类的实例放入一个集合中。

到目前为止一切顺利。

现在,我想要一个不同的集合,如果第一个字段是 equal ,它认为 Class1 的实例是相等的,从而使相等条件更弱。我什至可能想要另一组只考虑第二个字段作为检查相等性的字段。

有可能吗?如果有,怎么做?

【问题讨论】:

  • 将比较器与 TreeMap 一起使用。另一种选择是扩展 HashMap,使其使用 Hash 生成器而不是 hashCode()
  • 是否可以以某种方式扩展 HashSet?

标签: java set equals hashcode


【解决方案1】:

可以在提供仅检查您感兴趣的字段的自定义Comparator 时使用TreeSet 来获得该效果。

但是请注意,严格来说,这样的 TreeSet 不再是“正确的”Set,因为它实际上忽略了对象的 equal() 方法:

请注意,如果要正确实现Set 接口,集合维护的顺序(无论是否提供显式比较器)必须与equals 一致。 (参见ComparableComparator 了解与equals 一致 的精确定义。)这是因为Set 接口是根据equals 操作定义的,但@987654333 @instance 使用其compareTo(或compare)方法执行所有元素比较,因此从集合的角度来看,此方法认为相等的两个元素是相等的。一个集合的行为是明确定义的,即使它的排序与equals不一致;它只是不遵守Set 接口的一般约定。

【讨论】:

    【解决方案2】:

    标准 Java 库不支持此功能。

    而且(令人惊讶的是)Apache Commons Collections 或 Guava 库中似乎没有 MapSet 类支持此功能。

    如果您足够努力,可能还有其他库可以支持这一点。

    或者,您可以编写自己的...从标准的HashMap 代码开始。


    一种廉价而愉快的替代方法是为您的元素类型创建一个轻量级的包装类,它将大多数方法委托给被包装的类,并提供与原始类型不同的 equals / hashcode 对。这样做会有一点运行时损失……但值得考虑。

    Joachim 的建议也很好,除非你的系列可能特别大。 (TreeSetO(1) 相比,O(logN) 查找正确实现的哈希表。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-07-28
      • 1970-01-01
      • 1970-01-01
      • 2011-07-09
      • 2011-07-11
      • 2013-11-02
      • 1970-01-01
      相关资源
      最近更新 更多