Java中文本字符串的64位哈希函数是什么?

2022-08-31 16:11:40

我正在寻找一个哈希函数:

  1. 很好地散列文本字符串(例如,很少的冲突)
  2. 用Java编写,并广泛使用
  3. 奖励:适用于多个字段(而不是我连接它们并在连接字符串上应用哈希)
  4. 奖励:具有 128 位变体。
  5. 优点:不是 CPU 密集型的。

答案 1

你为什么不使用默认值的变体(一些非常聪明的人肯定会努力提高效率 - 更不用说已经看过这段代码的成千上万的开发人员眼睛)?longString.hashCode()

// adapted from String.hashCode()
public static long hash(String string) {
  long h = 1125899906842597L; // prime
  int len = string.length();

  for (int i = 0; i < len; i++) {
    h = 31*h + string.charAt(i);
  }
  return h;
}

如果你正在寻找更多的位,你可以使用BigInteger。编辑:

正如我在对@brianegge答案的评论中提到的,对于超过32位的哈希,没有太多用例,对于超过64位的哈希,很可能没有一个用例:

我可以想象一个巨大的哈希表分布在几十台服务器上,可能存储着数百亿个映射。对于这种情况,@brianegge在这里仍然有一个有效的观点:32位允许2 ^ 32(约43亿)不同的哈希键。假设有一个强大的算法,你仍然应该有相当多的冲突。使用64位(18,446,744,073亿个不同的密钥),无论您需要它做什么疯狂的场景,您都可以节省。但是,考虑128位密钥(340,282,366,920,938,463,463,374,607,431十亿个可能的密钥)的用例几乎是不可能的。

要组合多个字段的哈希值,只需执行XOR乘以素数并将它们相加:

long hash = MyHash.hash(string1) * 31 + MyHash.hash(string2);

小素数在那里是为了避免切换值的哈希代码相等,即{'foo','bar'}和{'bar','foo'}不相等,应该有不同的哈希码。XOR 是坏的,因为如果两个值都相等,它将返回 0。因此,{'foo','foo'} 和 {'bar','bar'} 将具有相同的哈希代码。


答案 2

今天(2018)的答案。SipHash.

它将比这里的大多数答案快得多,并且质量比所有答案都高得多。

番石榴图书馆有一个:https://google.github.io/guava/releases/23.0/api/docs/com/google/common/hash/Hashing.html#sipHash24-