HashMap做的containsKey行为方式不符合预期

时间:2015-07-01 18:34:06

标签: java hashmap contains

这是一个关于java的简单问题。

今天,当我不得不使用contains()查找某个班级Coord是否位于keySet() Coord时,我正在做一些寻路。 我发现,当我习​​惯预制方法containsKey()时,根本就没有按照我想要的方式工作。我做了一个测试,以了解发生了什么,现在是:

HashMap<Coord, Coord> test = new HashMap<Coord, Coord>();
test.put(new Coord(3, 3), new Coord(0, 0));

System.out.println("HashMap test for containsKey : " + test.containsKey(new Coord(3, 3)));

boolean containsKey = false;
for(Coord a : test.keySet())
{
    if(a.equals(new Coord(3, 3)))
    {
        containsKey = true;
    }
}

System.out.println("My test for containsKey : "+containsKey);

令人惊讶的是,这是我发现的:

HashMap test for containsKey : false
My test for containsKey : true

我只是想知道发生了什么以及为什么。

此外,这是Coord类:

public class Coord
{
    public float x, y;

    public Coord(float a, float b)
    {
        this.x = a;
        this.y = b;
    }

    @Override
    public boolean equals(Object b)
    {
        if(b instanceof Coord)
        {
            Coord casted = (Coord) b;
            return casted.x == x && casted.y == y;
        }
        return false;
    }
}

2 个答案:

答案 0 :(得分:6)

HashMap通过哈希码查找对象。合同的一部分是密钥类必须覆盖hashCode()以及equals()。单独对象的默认哈希码不相等,因此get找不到该对象。相反,当您遍历所有条目时,不会使用哈希码,因此只调用equals,并找到该对象。

要使用get查找,请在hashCode中覆盖Coord

每当您覆盖hashCode时覆盖equals总是好的,反之亦然。

答案 1 :(得分:0)

Hashmap实际上适用于hashing的校长。为了正确和预期结果,Hashmap中使用的密钥应覆盖equals()以及hashCode()

所以当你正在做test.containsKey(new Coord(3, 3))时,你正在创建一个新的Coord对象,因此它的哈希码与你把它放在地图上的Object不同,因为它的调用{{默认情况下,1}}类Object。所以hasCode()给出containsKey()

但是当你正在做false时,你正在调用覆盖a.equals(new Coord(3, 3)),它满足你在被覆盖的方法中放置的条件,这两个equals()对象都满足了这些条件,所以给出了输出为Coord

为了获得正确的结果,还要正确覆盖true

有关hashCode()如何在Java中工作的详细信息,您可以看到此博客here。希望这有帮助。