java使用哈希代码确定对象等价性
假设我有一个简单的类,它代表一个游戏块,名为^{
public class Tile {
public final int x;
public final int y;
public final int plane;
public Tile(int x, int y, int plane) {
this.x = x;
this.y = y;
this.plane = plane;
}
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
} else if (obj instanceof Tile) {
Tile other = (Tile) obj;
return other.x == x && other.y == y && other.plane == plane;
}
return false;
}
@Override
public int hashCode() {
return Objects.hash(x, y, plane);
}
}
作为一个负责任的公民,我实现了hashCode
方法,以确保根据equals
的合同,等价对象的哈希代码是相等的。然后我在想,对于任何两个Tile
对象,如果它们的x
、y
和plane
字段的值相同,那么哈希代码应该是相等的。那么,为什么不直接使用即来检查对象是否等效,而不是单独比较字段的值呢
更明确地说,为什么不替换:
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
} else if (obj instanceof Tile) {
Tile other = (Tile) obj;
return other.x == x && other.y == y && other.plane == plane;
}
return false;
}
简单地说:
@Override
public boolean equals(Object obj) {
return obj == this || obj != null && obj.hashCode() == hashCode();
}
我的一部分感觉这是一种糟糕的做法。这感觉就像是循环推理。然而,我想不出一个有效的、实际的理由来解释为什么这是一种糟糕的做法
简而言之:使用hashCode
的结果来确定equals
的结果是否合适
# 1 楼答案
不。可以这样想:对于三个
int
的每个组合,有2^32*2^32*2^32=2^96个不同的可能Tile
只有2^32个可能的
hashCode
因此,对于任何给定的
Tile
,将有2^64不同的可能的Tile
具有相同的哈希代码简而言之:散列码不是唯一的许多对象将碰巧具有相同的哈希代码,即使它们不相等
(通常,请记住
return 0;
是hashCode()
的有效实现。)# 2 楼答案
见^{} 合同:
两个“相等”的对象应该具有相同的哈希代码
两个“不等”对象可以具有相同的哈希代码