【问题标题】:Java Set can not distinguish different objectsJava Set 无法区分不同的对象
【发布时间】:2012-07-12 07:21:16
【问题描述】:

我有一个类 Human,其中包含两个字段,age(int) >名称(字符串)。在 Eclipse 中,我用这两个字段覆盖了 hashCode()equals() 方法。我还根据 age 字段创建了一个 Comparator

现在,我创建了一个 TreeSet 对象,该对象具有 Comparator 年龄,以及 Human 类的两个实例(具有不同的字段值) .然后我将这两个对象添加到集合中,但是,集合中始终只有一个对象。

为了理解问题,我打印出这两个对象的hash值,发现它们不一样。然后,我测试了他们的 equals() 方法,当我比较具有不同字段值的两个实例时,它确实输出 false。所以现在,我无法弄清楚为什么 TreeSet 不能处理(区分)问题。谁能给我一些帮助?非常感谢!

【问题讨论】:

    标签: java equals hashcode treeset


    【解决方案1】:

    TreeSet 根本不使用hashCode()equals()。它使用您作为参数传递的比较器(或对象的compareTo() 方法,如果它们是 Comparable 并且您不提供比较器)。如果 compare()(或compareTo())在比较这两个对象时返回 0,则 TreeSet 认为这两个对象相等。

    因此,如果您的比较器仅比较人类的年龄,则所有具有相同年龄的人类都将被视为相等。如果您希望人类在年龄和姓名相同时被认为是平等的,那么比较器应该按年龄进行比较,如果年龄比较返回 0,则按姓名进行比较。

    【讨论】:

    • 是的,很好看。在 compareTo() 方法中使用这两个字段。您想按年龄排序,因此按年龄内的姓名排序,那么年龄相同的 2 个姓名仍将正确排序但不会被视为相等(即您的 compareTo 将与 equals 一致)。
    • 但是在Java文档中,Comparator接口只有compare()方法,没有compareTo(),不是吗?
    • 是的。但是如果您的对象实现了 Comparable,则不需要将比较器传递给 TreeSet 的构造函数。在这种情况下,TreeSet 将使用它们的compareTo 方法比较对象。
    • 另外一个问题,对于使用 equals() 方法的 HashSet。当我不重写 equals() 方法时,为什么 HashSet 可以区分两个不同的对象?注意:我的 Human 类现在实现了 Comparable 接口!
    • 所有对象都有一个 equals() 和 hashCode() 方法,因为 java.lang.Object 实现了它们。这个默认实现只认为一个对象等于它自己。
    【解决方案2】:

    From the documentation

    之所以如此,是因为 Set 接口是根据等式定义的 操作,但 TreeSet 实例执行所有元素比较 使用它的 compareTo(或比较)方法,所以两个元素是 从集合的角度来看,这种方法认为相等的是, 平等的。集合的行为是明确定义的,即使它的排序是 与equals不一致;它只是不遵守总合同 设置界面。

    【讨论】:

      猜你喜欢
      • 2012-02-13
      • 2021-11-25
      • 1970-01-01
      • 2016-12-05
      • 2013-12-15
      • 1970-01-01
      • 2013-05-31
      • 2021-09-09
      • 2018-07-05
      相关资源
      最近更新 更多