2

我正在尝试使用 Java 中的 HashMap 检查和删除元素。它的键是我创建的称为 ClusterKey 的类型,它的值是我创建的称为 ClusterValue 的类型。

这是导致问题的代码:

ClusterKey ck = new ClusterKey(Long.parseLong(split[0].split("=")[1]), 
                        Integer.parseInt(split[1].split("ey")[1]));
if (arg == 0) keys.put(ck, new ClusterValue(index, false));
if (arg == 1) {
    if (keys.containsKey(ck)) {
        index = keys.get(ck).messageNo;
        keys.remove(ck);
    }
    keys.put(ck, new ClusterValue(index, true));
}

问题是即使 ClusterKey 与现有的 ClusterKey 相同, containsKey() 和 remove() 似乎也不认为它是相等的。我在类 ClusterKey 中实现了 equals() 来覆盖 Java 的 equals() 方法,如下:

class ClusterKey {
    long firstKey;
    int secondKey;
    public ClusterKey(long firstKey, int secondKey) {
        this.firstKey = firstKey;
        this.secondKey = secondKey;
    } public boolean equals(Object otherKey) {
        return this.firstKey == ((ClusterKey) otherKey).firstKey && this.secondKey == ((ClusterKey) otherKey).secondKey;
    }
}

所以,我很困惑。非常感谢你的帮助。

问候,丽贝卡

更新:感谢您对我的代码的建议和反馈。我能够通过将 hashCode() 添加到 ClusterKey 来解决问题,如下所示:

    } public boolean equals(Object otherKey) {
        return this.firstKey == ((ClusterKey) otherKey).firstKey && this.secondKey == ((ClusterKey) otherKey).secondKey;
    } public int hashCode() {
        return (int) firstKey + secondKey;
    } 
4

2 回答 2

3

为了使任何启用哈希的数据结构(如HashMap, HashSet)正常工作hashCode(),除了equals()方法之外,它的元素必须覆盖。原因是哈希码用于标识放置元素(在插入期间)或搜索(equals()在查找期间使用)的桶。

如果您不 override hashCode(),则使用默认实现 from Object#hashCode(),即使对于您认为等效的对象(该equals()方法返回true)也会返回不同的值。

这就是为什么你的

 hashMap.containsKey(ClusterKey key)

尽管密钥已经存在,但呼叫失败。由于哈希码不匹配,因此HashMap永远不会在正确的存储桶中查找密钥。因此,您equals()永远不会在这里被调用。

于 2013-07-16T18:47:29.793 回答
3

您将需要实施hashCode(),而不仅仅是equals为了让您ClusterKey作为HashMap.

具体来说,引用链接的 Javadocs:

如果两个对象根据 equals(Object) 方法相等,则对两个对象中的每一个调用 hashCode 方法必须产生相同的整数结果。

于 2013-07-16T18:33:21.293 回答