HashMap 做 containsKey 的方式不符合预期
HashMap way of doing containsKey not behaving as expected
今天我正在做一些寻路,当我不得不使用 contains()
来查找 class Coord
是否在 Coord
的另一个 keySet()
中时.
我发现当我使用预制方法 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
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;
}
}
HashMap
s 通过哈希码查找对象。合同的一部分是密钥 class 必须覆盖 hashCode()
以及 equals()
。不同对象的默认哈希码不相等,因此 get
找不到该对象。相反,当您遍历所有条目时,不使用散列码,因此仅调用 equals
并找到对象。
要使用 get
找到它,请覆盖 Coord
中的 hashCode
。
每次覆盖 equals
时覆盖 hashCode
总是好的,反之亦然。
Hashmap
实际上是在 hashing 的基础上工作的。为了获得正确和预期的结果,Hashmap
中使用的密钥应覆盖 equals()
以及 hashCode()
.
所以在上面,当你在做 test.containsKey(new Coord(3, 3))
时,你正在创建一个新的 Coord
对象,所以它的哈希码不同于你把它放在地图上的 Object
,因为它的调用默认为 Object
class hasCode()
。所以 containsKey()
给出 false
但是当你在做 a.equals(new Coord(3, 3))
时你正在调用覆盖 equals()
这满足了你在覆盖方法中设置的条件,这两个 Coord
对象都满足了,所以输出为 true
.
为了获得正确的结果,还要正确覆盖 hashCode()
。
有关 HashMap
如何在 Java 中工作的更多信息,您可以查看此博客 here。希望这对您有所帮助。
今天我正在做一些寻路,当我不得不使用 contains()
来查找 class Coord
是否在 Coord
的另一个 keySet()
中时.
我发现当我使用预制方法 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
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;
}
}
HashMap
s 通过哈希码查找对象。合同的一部分是密钥 class 必须覆盖 hashCode()
以及 equals()
。不同对象的默认哈希码不相等,因此 get
找不到该对象。相反,当您遍历所有条目时,不使用散列码,因此仅调用 equals
并找到对象。
要使用 get
找到它,请覆盖 Coord
中的 hashCode
。
每次覆盖 equals
时覆盖 hashCode
总是好的,反之亦然。
Hashmap
实际上是在 hashing 的基础上工作的。为了获得正确和预期的结果,Hashmap
中使用的密钥应覆盖 equals()
以及 hashCode()
.
所以在上面,当你在做 test.containsKey(new Coord(3, 3))
时,你正在创建一个新的 Coord
对象,所以它的哈希码不同于你把它放在地图上的 Object
,因为它的调用默认为 Object
class hasCode()
。所以 containsKey()
给出 false
但是当你在做 a.equals(new Coord(3, 3))
时你正在调用覆盖 equals()
这满足了你在覆盖方法中设置的条件,这两个 Coord
对象都满足了,所以输出为 true
.
为了获得正确的结果,还要正确覆盖 hashCode()
。
有关 HashMap
如何在 Java 中工作的更多信息,您可以查看此博客 here。希望这对您有所帮助。