12

实现类似方法的最快和更健壮(就唯一性而言)的方法是什么

public abstract String hash(String[] values);

values[]数组有 100 到 1,000 个成员,每个成员都有几十个字符,并且该方法每次需要在不同的values[]数组上运行大约 10,000 次/秒。

应该使用StringBuilder缓冲区构建长字符串,然后在缓冲区内容上调用哈希方法,还是继续为每个字符串调用哈希方法更好values[]

显然,需要至少 64 位的散列(例如,MD5)来避免冲突,但是有没有什么更简单、更快的方法可以在相同的质量下完成?

例如,关于

public String hash(String[] values)
{
    long result = 0;

    for (String v:values)
    {
        result += v.hashCode();
    }

    return String.valueOf(result);
}
4

5 回答 5

11

由于其线性特性,绝对不要使用简单的加法,但您可以稍微修改您的代码以实现非常好的分散。

public String hash(String[] values) {
  long result = 17;
  for (String v:values) result = 37*result + v.hashCode();
  return String.valueOf(result);
}
于 2012-05-14T16:43:30.503 回答
8

它不提供 64 位哈希,但鉴于问题的标题,可能值得一提的是,自 Java 1.7 以来就有java.util.Objects#hash(Object...)

于 2017-03-03T23:14:47.837 回答
5

这是使用 Java 7 中可用的 Objects 类的简单实现。

@Override
public int hashCode()
{
    return Objects.hash(this.variable1, this.variable2);
}
于 2018-12-13T17:37:17.250 回答
2

在组合方法时,您应该注意创建弱点。(java哈希函数和你自己的)。我对级联密码做了一些研究,这就是一个例子。(添加可能会干扰 hashCode() 的内部结构。

hashCode() 的内部结构如下所示:

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

所以将数字加在一起会导致数组中所有字符串的最后一个字符被添加,这不会降低随机性(这对于哈希函数来说已经足够糟糕了)。

如果您想要真正的伪随机性,请查看FNV哈希算法。它是目前最快的哈希算法,专为在 HashMaps 中使用而设计。

它是这样的:

    long hash = 0xCBF29CE484222325L;
    for(String s : strings)
    {
        hash ^= s.hashCode();
        hash *= 0x100000001B3L;
    }

^ 这不是 FNV 的实际实现,因为它需要整数而不是字节作为输入,但我认为它也能正常工作。

于 2012-05-14T16:54:03.457 回答
1

首先,哈希码通常是数字,例如int。此外,您的哈希函数版本创建 int ,然后使其字符串表示恕我直言没有任何意义。

我会改进你的哈希方法如下:

public int hash(String[] values) {
    long result = 0;
   for (String v:values) {
        result = result * 31 + v.hashCode();
    }
    return result;
}

看看hashCode()在课堂上实现java.lang.String

于 2012-05-14T16:46:26.167 回答