为什么String hashCode没有大小限制?

时间:2019-05-08 11:43:37

标签: java hash hashcode

它使我感到困扰了一段时间,但是我还没有找到任何令人信服的答案,那么为什么Java String中的hashCode函数没有任何大小限制?以下是我发现的here的实现:

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;
}

首先,我了解临时变量h的用法,该用法在多个线程中使用String时很有意义。其次,我们都知道上述实现不能避免哈希冲突(没有hashCode实现可以),因此基本上我们应该将此功能仅视为“性能改进”,这对哈希表或类似结构很有用

如果是这样,那么为什么要允许我们有100 MB字符串,我们基于 all 计算哈希值吗?增加一些限制不是更有意义吗? 32/128甚至1024个字符,但不是整个value.length?是的,如果我们有两个具有相同前缀且长度相同的字符串(只要达到我们的限制),那么我们将发生哈希冲突,但是我们仍然无法避免冲突,因此从性能的角度来看,我个人会更改为类似的循环:

int limit = value.length > 32 ? 32 : value.length;
for (int i = 0; i < limit; i++) {
    h = 31 * h + val[i];
}

你怎么看?

1 个答案:

答案 0 :(得分:3)

浮现在脑海的几个可能原因:

  1. 通常情况下,字符串仅在开头或结尾处有所不同,例如所有StackOverflow问题URL均以“ https://stackoverflow.com/questions/”开头。因此,将hashCode限制为仅字符的子集将导致不必要的冲突,并且对于某些字符串集会导致许多冲突。您提出的算法将导致每个stackoverflow问题URL都具有相同的hashCode!

  2. hashCode快速且易于记忆,尚不清楚将hashCode限制为一定的长度会带来显着的性能改进,尤其是因为它总是在创建String(O(n)操作)之前,并且通常然后调用equals(也是O(n))。

  3. 旧版原因。 String.hashcode被指定为使用特定算法。现有的应用程序依赖于此规范。即使现在认为该优化是必要的,也必须在不破坏向后兼容性的情况下进行。