哈希映射中的双倍
我正在考虑使用Double作为HashMap的关键,但我知道浮点比较是不安全的,这让我开始思考。双精度类上的等式方法是否也不安全?如果是这样,那就意味着hashCode方法也可能是不正确的。这意味着使用 Double 作为 HashMap 的键将导致不可预测的行为。
任何人都可以在这里证实我的任何猜测吗?
我正在考虑使用Double作为HashMap的关键,但我知道浮点比较是不安全的,这让我开始思考。双精度类上的等式方法是否也不安全?如果是这样,那就意味着hashCode方法也可能是不正确的。这意味着使用 Double 作为 HashMap 的键将导致不可预测的行为。
任何人都可以在这里证实我的任何猜测吗?
简短的回答:别这样
长答案:以下是密钥的计算方法:
实际的键将是一个对象,因为键必须是对象。这是它的方法:java.lang.Double
hashCode()
public int hashCode() {
long bits = doubleToLongBits(value);
return (int)(bits ^ (bits >>> 32));
}
该方法基本上采用8个字节并表示它们的长度。因此,这意味着双精度计算中的微小变化可能意味着很多,并且您将有关键的失误。doubleToLongBits()
如果您可以在点后确定给定的点数 - 乘以10^(点后的位数)并转换为int(例如 - 2位数字乘以100)。
这将更加安全。
我认为你是对的。虽然双打的哈希是整数,但双精度可能会弄乱哈希。这就是为什么,正如Josh Bloch在 Effective Java 中提到的,当你使用 double 作为哈希函数的输入时,你应该使用 doubleToLongBits()。同样,将 floatToIntBits 用于浮点数。
特别是,要使用双精度作为哈希值,按照Josh Bloch的食谱,您可以这样做:
public int hashCode() {
int result = 17;
long temp = Double.doubleToLongBits(the_double_field);
result = 37 * result + ((int) (temp ^ (temp >>> 32)));
return result;
}
这是来自 Effective Java 的第 8 项,“当你覆盖等于时,总是覆盖哈希码”。可以在本书章节的pdf中找到它。
希望这有帮助。