【问题标题】:Java HashMap containsKey always falseJava HashMap containsKey 始终为 false
【发布时间】:2012-10-04 17:16:37
【问题描述】:

我有一个有趣的情况,我将Coordinate 存储到HashMap<Coordinate, GUIGameField> 中。

现在,奇怪的是,我有一段代码,它应该保护,不应该使用两次坐标。但是如果我调试这段代码:

if (mapForLevel.containsKey(coord)) {
    throw new IllegalStateException("This coordinate is already used!");
} else {
    ...do stuff...
}

...containsKey 始终返回 false,尽管我将哈希码为 9731 的坐标存储到地图中,并且当前坐标也具有哈希码 9731。

之后,mapForLevel.entrySet() 看起来像:

(java.util.HashMap$EntrySet) [(270,90)=gui.GUIGameField@29e357, (270,90)=gui.GUIGameField@ca470]

我可能做错了什么?我没有主意了。感谢您的帮助!

public class Coordinate {
    int xCoord;
    int yCoord;

    public Coordinate(int x, int y) {
        ...store params in attributes...
    }

    ...getters & setters...

    @Override
    public int hashCode() {
        int hash = 1;
        hash = hash * 41 + this.xCoord;
        hash = hash * 31 + this.yCoord;
        return hash;
    }
}

【问题讨论】:

  • 您是否在 Coordinate 类中同时覆盖 equals()hashCode() 方法?

标签: java hashmap contains


【解决方案1】:

除了hashCode 之外,您还应该覆盖equals 以使其正常工作。

编辑:我错误地说你应该在你的equals 中使用hashCode - 这是不正确的。虽然hashCode 必须为两个相等的对象返回相同的结果,但它仍然可能为不同的对象返回相同的结果。

【讨论】:

  • equals 不应使用hashCode
【解决方案2】:

Coordinate 类中定义 hashCode 方法。 确保它为唯一对象返回唯一代码,并且为相同对象返回相同代码。

【讨论】:

  • 好吧,我已经像代码片段所示那样做了,但是既然现在已经解决了,还是感谢你的想法。
【解决方案3】:

您似乎忘记为您的坐标类实现equals() 方法。这是合同要求的。 Hah 使用 equals 比较具有相同哈希码的 2 个条目。在您的情况下,Object.equals() 的调用对于 2 个不同的对象总是不同的,因为它基于对内存中对象的引用。

【讨论】:

  • 是的,同样感谢你,我认为 hashCode 在这里做交易。
【解决方案4】:

您需要在 hashCode 旁边实现 equals 的原因是哈希表的工作方式。

哈希表将整数值(键的哈希)与值相关联。 将其视为一组 Value 对象。当您在此表中插入时,value 存储在位置 key.hashCode()

这使您可以“立即”找到表格中的任何对象。您只需计算该对象的 hashCode,您就会知道它在桌子上的位置。把它想象成一棵树,你需要在树中导航才能找到对象)。

但是,这种方法存在一个问题:可能有具有相同哈希码的多个对象。 这会导致您错误地将两个(或更多)键与相同的值相关联。这称为碰撞

有一个简单的方法可以解决这个问题:不是将每个哈希码映射到一个 Value,而是将其映射到一个 Key-Value 对列表。 p>

现在,每次您在哈希映射中查找对象时,在计算哈希后,您需要遍历该列表(与该哈希码相关的“值”列表)并找到正确的 一个。

这就是为什么您总是需要在哈希映射的键上实现 equals

注意:哈希表实际上比这要复杂一些,但想法是一样的。您可以阅读有关冲突解决的更多信息here

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-06
    • 2012-03-29
    相关资源
    最近更新 更多