【问题标题】:Treemap ignoring my override of the equals functionTreemap 忽略了我对 equals 函数的覆盖
【发布时间】:2012-03-16 19:04:02
【问题描述】:

我有一个 TreeMap,其中 RobotKey 是一个由字符串字段域和长字段时间戳组成的类。 RobotKey 的实现如下:

@Override
public boolean equals(Object obj) {
    if (this.domain.equals(((RobotKey) obj).getDomain()))
        return true;
    return false;
}

并且treemap是按照如下compareTo函数排序的:

@Override
public int compareTo(RobotKey arg0) {
    if (this.lastAccessed < arg0.lastAccessed)
        return -1;
    else if (this.domain.equals(arg0.getDomain()))
        return 0;
    else
        return 1;
}

所以基本上,地图是通过域名访问的,并且是根据时间戳排序的。

我做了 treemap.get(RobotKey e) ,其中 e 与 treemap 中的现有条目具有相同的域名,但时间戳不同。这应该返回正确的 RobotValue,因为 Map 操作是使用 equals 完成的。但它反而返回我 null 表示未找到 RobotKey。知道为什么会这样吗?我做错了什么,我该如何解决?谢谢!

【问题讨论】:

    标签: java treemap


    【解决方案1】:

    问题在于您的 equals 和 compareTo 方法不一致。 compareTo 必须返回 0 当且仅当 equals 返回 true,据我记得 TreeMap(或 TreeSet)不调用 equals 方法,它只是使用 compareTo 及其结果来指示重复键。

    【讨论】:

    • 嗨,我的 compareTo 和我的 equals 函数是一致的。在这两个函数中,如果域名是相同的字符串,我会返回 0 或 true。但我认为您可能是对的,您是否看到了我遗漏的任何不一致之处?
    • 哦,实际上我看到了我的问题。 return 0 在我的 else if 语句中,如果 if 为真,则可能不会被调用。
    • 您必须使其在domainlastAccessed 方面保持一致。现在,如果域不同但lastAccessed 相等,您将返回1,这很糟糕。
    【解决方案2】:

    任何时候你覆盖equals你也应该覆盖hashCode。

    查看the documentation 中的equals 和hashCode 合约,上面写着If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.

    您的实现被破坏了,因为映射使用 hashCode 来确定对象属于哪个存储桶,然后可能使用 equals 来确定对象是否在存储桶中。在您的情况下,您认为相等的两个对象会生成不同的哈希码,因此该集合不会在同一个存储桶中查找。

    【讨论】:

    • 据我所知 TreeMap 不是基于哈希的地图
    • 是的,我只是尝试覆盖哈希码函数以返回 hte 域字符串的哈希码,但这不起作用。
    • 我知道,TreeMap 和 TreeSet 不会在它们包含的对象上调用 equals 方法。
    • 啊,我没有专门看TreeMap。在任何情况下,打破 equals/hashCode 合约都是不好的。在这种情况下你有一个很好的观点,我会投票赞成你的答案,因为它解决了手头的问题。
    • 完全同意,equalshashCode 应该是一致的,因为谁能保证对象永远不会存储在 HashMap、HashSet 中?顺便说一句,equalscompareTo 也应该是一致的,因为 TreeSet 和 TreeMap 的原因相同。
    猜你喜欢
    • 2020-02-09
    • 2010-10-30
    • 2013-06-02
    • 1970-01-01
    • 1970-01-01
    • 2016-05-07
    • 2020-03-30
    • 2015-04-25
    • 1970-01-01
    相关资源
    最近更新 更多