此问题是my post在CodeReview提交给{{3}}的回复的结果。
我有一个名为class
的{{1}},它基本上是“用于封装在2D空间中表示的点”。我已经覆盖了Point
函数,如下所示:
hashcode()
让我澄清(对于那些没有查看上述链接的人)我的...
@Override
public int hashCode() {
int hash = 0;
hash += (int) (Double.doubleToLongBits(this.getX())
^ (Double.doubleToLongBits(this.getX()) >>> 32));
hash += (int) (Double.doubleToLongBits(this.getY())
^ (Double.doubleToLongBits(this.getY()) >>> 32));
return hash;
}
...
使用两个Point
:double
和x
来表示其坐标
问题:
当我运行这个方法时,我的问题很明显:
y
我得到输出:
public static void main(String[] args) {
Point p1 = Point.getCartesianPoint(12, 0);
Point p2 = Point.getCartesianPoint(0, 12);
System.out.println(p1.hashCode());
System.out.println(p2.hashCode());
}
这显然是个问题。基本上我打算让我的1076363264
1076363264
返回相等的哈希码以获得相等的点。如果我在其中一个参数声明中反转顺序(即在其中一个中交换hashcode()
并使用12
得到相等的1
s),我得到正确的(相同的)结果。如何在保持哈希的质量或唯一性的同时纠正我的方法?
答案 0 :(得分:5)
如果没有关于双打中数字性质的数据的更多信息,则无法获得两个唯一的双精度的整数哈希码。
<强>为什么吗
int存储为32位表示,双精度存储为64位表示(see the Java tutorial)。
因此,您试图在32位空间中存储128位信息,因此它永远不会给出唯一的哈希值。
<强>然而强>
答案 1 :(得分:3)
试试这个
public int hashCode() {
long bits = Double.doubleToLongBits(x);
int hash = 31 + (int) (bits ^ (bits >>> 32));
bits = Double.doubleToLongBits(y);
hash = 31 * hash + (int) (bits ^ (bits >>> 32));
return hash;
}
此实现遵循Arrays.hashCode(double a[])
模式。
它产生这些哈希码:
-992476223
1076364225
您可以找到有关如何在Effective Java Item中编写好hashCode的建议。 9
答案 2 :(得分:1)
这可能是一个愚蠢的想法,如果你正在使用+这是一个对称操作,你就会遇到对称问题。如果您使用非对称操作(例如除法(检查分母== 0)或减去?或者你在文学中找到或发明自己的任何其他东西。
答案 3 :(得分:1)
您是否已使用Arrays.hashCode中已存在的代码?
Arrays.hashCode(new double[]{x,y});
这就是番石榴在Objects.hashCode.
中使用的例子如果你有Java 7,只需:
Objects.hash(x,y)