这是一个关于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;
}
}
答案 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。希望这有帮助。