6

我已经为.NET中的方法提出了类似的问题。string.GetHashCode()从那时起,我了解到,如果我们要在不同的机器上使用哈希码,我们不能依赖于内置类型的哈希码的隐式实现。因此,我假设 Java 的实现String.hashCode()在不同的硬件配置中也是不稳定的,并且可能在不同的虚拟机中表现不同(不要忘记不同的虚拟机实现)

目前我们正在讨论一种在 Java 中通过哈希将字符串安全地转换为数字的方法,但是哈希算法必须在集群的不同节点之间保持稳定,并且评估速度快,因为使用频率很高。我的队友坚持使用原生hashCode方法,我需要一些合理的论据来让他们重新考虑另一种方法。目前,我只能想到机器配置(x86 和 x64)之间的差异,可能是某些机器上 JVM 的不同供应商(在我们的案例中几乎不适用)和字节顺序差异,具体取决于算法所使用的机器跑。当然,可能还要考虑字符编码。

虽然所有这些事情都出现在我的脑海中,但我不能 100% 确定其中任何一个都是足够有力的理由,我会感谢您在这方面的专业知识和经验。这将帮助我建立更有力的论据来支持编写自定义散列算法。另外,我很感激关于在实施时不应该做什么的建议。

4

2 回答 2

13

的实现在文档String.hashCode()指定,因此保证一致:

String 对象的哈希码计算为

  s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]

使用 int 算术,其中 s[i] 是字符串的第 i 个字符,n 是字符串的长度,^ 表示求幂。(空字符串的哈希值为零。)

对于 Java,所有这些操作都是独立于平台实现的——例如,平台字节顺序是无关紧要的。

也就是说,如果您是从文件或其他字节源获取它,那么获取它的方法可能会很棘手String在这种情况下,只要您明确指定一个Charset. (请记住,Strings 本身没有不同的编码;编码是a和 a之间转换的规范。)byte[]String

于 2013-03-28T22:55:24.477 回答
3

您可以查看源代码,如下所示。据我所见(经过 10 秒的分析),这应该在机器和架构之间保持稳定。路易斯通过引用规范来证实这一点,如果你相信规范,那就更好了。:-)

但是,如果不同的 JRE 选择以不同的方式实现它并违反规范,这可能会有所不同。

public int hashCode() {
    int h = hash;
    if (h == 0) {
        int off = offset;
        char val[] = value;
        int len = count;

        for (int i = 0; i < len; i++) {
            h = 31*h + val[off++];
        }

        hash = h;
    }

    return h;
}
于 2013-03-28T22:57:05.390 回答