HashMap way of doing containsKey not behaving as expected

孤街醉人 提交于 2019-12-01 04:50:35

问题


Today I was doing some pathfinding when I had to use contains() to find if a class Coord was in an other keySet() of Coord. I found that when I used to premade method containsKey(), it was simply not working as I wanted. I made a test to find out what is happening and here it is:

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);

And surprisingly, here is what I found :

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

I just wanted to know what is happening and why.

Also, here is the Coord class :

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;
    }
}

回答1:


HashMaps find objects by their hash code. Part of the contract is that the key class must override hashCode() as well as equals(). The default hash codes for separate objects aren't equal, so the object isn't found by get. In contrast, when you loop over all entries, the hash code isn't used, so only equals is called, and the object is found.

To find it using get, override hashCode in Coord.

It is always good to override hashCode whenever you override equals, and vice versa.




回答2:


Hashmap actually works on the principal of hashing. For correct & expected results, the key used in the Hashmap should override equals() as well as hashCode().

So above while you are doing test.containsKey(new Coord(3, 3)) you are creating a new Coord object so its hashcode is different from the Object which you have put it the map, as its callingObject class hasCode() by default. So containsKey() giving a false

But while you are doing a.equals(new Coord(3, 3)) you are calling overriden equals() which is satisfying the conditions you have put in your overridden method, which is being satisfied by both Coord objects, so giving the output as true.

For proper results also override hashCode() correctly.

For more info on how HashMap works in Java, you can see this blog here. Hope this helped.



来源:https://stackoverflow.com/questions/31169067/hashmap-way-of-doing-containskey-not-behaving-as-expected

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!