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 的概念相当于位移。我也知道当我们将一个大数乘以一个大奇数素数时,我们仍然会出现溢出(因此信息丢失)。我不明白为什么由大奇数乘法引起的信息丢失比由大偶数乘法引起的信息丢失更可取。

4

2 回答 2

6

对于偶数乘法器,乘法后的最低有效位始终为零。对于奇数乘法器,最低有效位是 1 或 0,具体取决于先前的值result是什么。因此,偶数乘法器失去了低位的不确定性,而奇数乘法器保留了它。

于 2012-06-06T13:40:58.987 回答
1

没有大的偶素数这样的东西——唯一的偶素数是 2。

除此之外 - 使用中等大小的素数 # 而不是像 3 或 5 这样的小素数的一般目的是最大限度地减少两个对象最终具有相同哈希值的可能性,无论是否溢出。

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

于 2012-06-06T13:40:37.530 回答