哈希映射中的双倍

2022-09-02 03:11:53

我正在考虑使用Double作为HashMap的关键,但我知道浮点比较是不安全的,这让我开始思考。双精度类上的等式方法是否也不安全?如果是这样,那就意味着hashCode方法也可能是不正确的。这意味着使用 Double 作为 HashMap 的键将导致不可预测的行为。

任何人都可以在这里证实我的任何猜测吗?


答案 1

简短的回答:别这样

长答案:以下是密钥的计算方法:

实际的键将是一个对象,因为键必须是对象。这是它的方法:java.lang.DoublehashCode()

public int hashCode() {
  long bits = doubleToLongBits(value);
  return (int)(bits ^ (bits >>> 32));
}

该方法基本上采用8个字节并表示它们的长度。因此,这意味着双精度计算中的微小变化可能意味着很多,并且您将有关键的失误。doubleToLongBits()

如果您可以在点后确定给定的点数 - 乘以10^(点后的位数)并转换为int(例如 - 2位数字乘以100)。

这将更加安全。


答案 2

我认为你是对的。虽然双打的哈希是整数,但双精度可能会弄乱哈希。这就是为什么,正如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中找到它。

希望这有帮助。