只有两个int属性的定制类的hashCode是什么?
在Java中,我有一个用int坐标表示点的类
public class Point {
int x = -1;
int y = -1;
public Point (int xNew, int yNew) {
x = xNew; y = yNew;
}
public boolean equals (Object o) {
// no need for (o instanceof Point) by design
return x == ((Point)o).x && y == ((Point)o).y;
}
}
我使用Point
类的对象作为HashMap
中的键,并作为HashSet
中的元素。
hashCode
函数的最佳候选者是什么?我会将其加倍,这样左边的部分是x,右边的部分是y,例如:
x = 4, y = 12
,则hashCode
返回4.12
。但通过实现,它不能是Double,只能是int。
这不是一个选项:
public int hashCode() {
// no need to check for exception parseInt since x and y are valid by design
return Integer.parseInt(Integer.toString(x) + Integer.toString(y));
}
因为值x
和y
可能太长,所以它们加在一起不会被转换。
解决方案
您不能更改hashCode
的类型,也不应该更改。
我只会这样做:
public int hashCode() {
return x * 31 + y;
}
请注意,这意味着在大多数情况下(a,b)不同于(b,a)(不同于加法或异或运算)。如果您在实际生活中经常使用"已切换"值的键,这可能会很有用。
它不是唯一的-但散列代码不一定是唯一的。对于相同的值,只是必须相同(为了正确),而对于不相等的值,它们"通常"是不同的,并具有合理的分布。
总的来说,我通常遵循Josh Bloch在《Efficient Java:
》中建议的模式:public int hashCode() {
int hash = 17;
hash = hash * 31 + field1Hash;
hash = hash * 31 + field2Hash;
hash = hash * 31 + field3Hash;
hash = hash * 31 + field4Hash;
...
return hash;
}
其中field1Hash
将是引用类型字段的散列代码(或0表示空引用),int
本身是整数值的散列代码,long
是从64位到32位的某种散列,等等。
编辑:我记不清为什么31和17在一起工作得很好的细节。它们都是素数这一事实可能有用--但据我所知,这种散列背后的数学原理通常是合理的(尽管不如预先知道可能值分布的散列好),要么很难理解,要么就不能很好地理解。我知道乘以31比较便宜(左移5并减去原值)...
相关文章