问题
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:
HashMap
s 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