我最近在 java 中计算双精度元组的哈希码时遇到了一个奇怪的情况。假设您有两个元组 (1.0,1.0) 和 (Double.POSITIVE_INFINITY,Double.POSITIVE_INFINITY)。使用Joshua Bloch 的 Effective Java(第 7 项)中所述的习语,这两个元组将不被视为相等(想象这些元组是对象)。但是,使用条款 8 中所述的公式来计算hashCode()
每个元组的计算结果是相同的。
所以我的问题是:这个公式有什么奇怪的地方是我在编写公式时错过的,还是只是哈希码冲突的奇怪情况?
这是说明情况的简短比较方法(我将其编写为 JUnit4 测试,但它应该很容易转换为main
方法)。
@Test
public void testDoubleHashCodeAndInfinity(){
double a = 1.0;
double b = 1.0;
double c = Double.POSITIVE_INFINITY;
double d = Double.POSITIVE_INFINITY;
int prime = 31;
int result1 = 17;
int result2 = 17;
long temp1 = Double.doubleToLongBits(a);
long temp2 = Double.doubleToLongBits(c);
//this assertion passes successfully
assertTrue("Double.doubleToLongBits(Double.POSITIVE_INFINITY" +
"==Double.doubleToLongBits(1.0)",temp1!=temp2);
result1 = prime*result1 + (int)(temp1^(temp1>>>32));
result2 = prime*result2 + (int)(temp2^(temp2>>>32));
//this assertion passes successfully
assertTrue("Double.POSITIVE_INFINITY.hashCode()" +
"==(1.0).hashCode()",result1!=result2);
temp1 = Double.doubleToLongBits(b);
temp2 = Double.doubleToLongBits(d);
//this assertion should pass successfully
assertTrue("Double.doubleToLongBits(Double.POSITIVE_INFINITY" +
"==Double.doubleToLongBits(1.0)",temp1!=temp2);
result1 = prime*result1+(int)(temp1^(temp1>>>32));
result2 = prime*result2+(int)(temp2^(temp2>>>32));
//this assertion fails!
assertTrue("(1.0,1.0).hashCode()==" +
"(Double.POSITIVE_INFINITY,Double.POSITIVE_INFINITY).hashCode()",
result1!=result2);
}