【问题标题】:Why libraries prefer to recalculate hashcode on immutable objects in edge case?为什么库更喜欢在边缘情况下重新计算不可变对象的哈希码?
【发布时间】:2014-01-13 19:34:59
【问题描述】:

在番石榴代码(我认为这是高质量代码的示例之一)中,我发现了以下片段:

// If the cachedHashCode is 0, it will always be recalculated, unfortunately.
private transient int cachedHashCode;

public final int hashCode() {
   // Racy single-check.
  int code = cachedHashCode;
  if (code == 0) {
    cachedHashCode = code = element.hashCode();
  }
  return code;
}

所以“如果 cachedHashCode 为 0,它总是会被重新计算,不幸的是”。另一个例子是JDKString.hashCode

public int hashCode() {
    int h = hash;
    if (h == 0 && value.length > 0) {
        char val[] = value;

        for (int i = 0; i < value.length; i++) {
            h = 31 * h + val[i];
        }
        hash = h;
    }
    return h;
}

它也尝试计算一次哈希码,但如果String的hashCode为0则失败(此类字符串的示例为"\0")。

避免此类重新计算的简单解决方案是增加对计算的额外检查:

if (hash == 0) hash++;

虽然在一般情况下它会稍微减慢hashCode 的计算速度,但这个技巧可以避免在反复计算时(并且缓慢(例如对于长字符串))一次又一次地计算最坏的情况。 为什么在 guava ImmutableSet 和 JDK String 中没有使用它?

编辑

最近的 Java 7 版本添加了自定义 String.hash32 实现,其中包含对这种特殊情况的处理:

       // ensure result is not zero to avoid recalcing
       h = (0 != h) ? h : 1;

【问题讨论】:

  • 为“\0”之类的字符串重新计算哈希码的代价可能太小了,以至于不值得放入诸如“if (hash == 0) 之类的大学风格/人为的代码中) 哈希++;"

标签: java caching guava immutability hashcode


【解决方案1】:

这样做是为了节省空间。

例如,如果String 没有使用哈希值零来表示(未缓存),那么String 类将需要一个额外的布尔标志来表示哈希值未缓存。

因此,权衡是每次重新计算哈希的概率为 40 亿分之一1,而不是为每个字符串对象增加一个单词。


1 - 这假设人们从所有可能的 Java 字符串的域中随机选择字符串对象。真正的程序不是这样工作的……但重点是重新计算哈希码的影响不大,除非你故意为此设计应用程序。

【讨论】:

  • 除了希望保持与任何持久字符串哈希值的兼容性之外,如果让哈希码逻辑检查来自非空字符串的计算值是否为零,并且,如果是这样,增加它?根据优化器的不同,这将归结为 1-3 条快速指令,并且可以避免潜在的灾难性最坏情况行为。
  • 每次散列(新)字符串时都会执行这 1-3 条指令。并且散列一个空字符串的成本并没有那么大。 (灾难性的夸大其词!)您提出的优化结果可能会导致大多数用例的减速。
  • 散列一个空字符串的成本是微不足道的,这就是为什么让一个空字符串返回零不会是一个问题。可能是灾难性的,重复查找某些大字符串需要的时间比查找其他字符串要长几个数量级。
  • @supercat - 但是假设字符串是随机选择的,那么你会得到一个坏情况的概率非常非常低。问题在于故意制作散列值为零的长字符串......为了导致某些东西中断。这是一种特殊情况,如果情况需要,可以通过其他方式处理。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-12
  • 2016-07-27
  • 1970-01-01
相关资源
最近更新 更多