Effective Java教材中关于哈希码示例的解释

5
这是第9条的示例代码:

// 这里是代码

public final class PhoneNumber {
  private final short areaCode;
  private final short prefix;
  private final short lineNumber;

  @Override
  public int hashCode() {
    int result = 17;
    result = 31 * result + areaCode;
    result = 31 * result + prefix;
    result = 31 * result + lineNumber;
    return result;
  }
}

第48页写道:"选择值31是因为它是个奇质数。如果选偶数并且乘法溢出,信息就会丢失,因为乘以2等同于移位操作。"

我理解乘以2等同于位移的概念。我也知道当我们用大的奇质数去乘以一个大数时,仍然会发生溢出(因此会有信息丢失)。但我不明白为什么因为大奇质数导致的信息丢失比因为大偶数导致的信息丢失更可取。


1
除了2以外,没有其他偶数是质数。 - Prince John Wesley
哎呀!我简直不敢相信我居然忘了这个。我想今天我可能有点傻。谢谢 :) - Kes115
3
这可能是与 https://dev59.com/gnVC5IYBdhLWcg3wbQfA 相同的问题。 - Justin Blank
2个回答

6

使用偶数乘数,最低有效位在乘法后始终是零。 使用奇数乘数,最低有效位取决于result的先前值是一还是零。 因此,偶数乘数正在失去有关低位的不确定性,而奇数乘数正在保留它。


1

不存在大的偶数质数 - 唯一的偶数质数是2。

除此之外 - 使用中等大小的质数而不是像3或5这样的小质数的一般观点是为了最小化两个对象最终具有相同的哈希值的机会,无论是否溢出。

溢出的风险本身并不是问题; 真正的问题是被散列的对象集的哈希码值分布如何。因为哈希码在像HashSet、HashMap等数据结构中使用,所以您希望最小化可能共享相同哈希码的对象数量,以优化对这些集合的查找时间。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接