【问题标题】:Order Independent Hash in JavaJava中的顺序独立哈希
【发布时间】:2017-11-13 06:07:23
【问题描述】:

我想用 Java 计算一组字符串的哈希值。是的,我可以对字符串进行排序并计算 MD5 哈希迭代使用digest.update。 但我宁愿省略排序并使用类似combineUnordered https://github.com/google/guava/wiki/HashingExplained 有很多类似的问题问同样的问题,例如Order-independant Hash Algorithm 但它们都没有提供一个简单的示例来展示如何在 Java 中迭代计算与顺序无关的哈希。

【问题讨论】:

  • 为什么要覆盖集合的哈希算法?
  • @SzigyártóMihály 无需覆盖,我正在寻找一个简单的示例。我知道 MD5,它对订单敏感,而 MurmurHash 不应该,但我找不到使用它的例子。
  • 集合使用item的哈希值之和,不依赖于顺序。

标签: java hash set unordered


【解决方案1】:

只需对每个散列进行异或运算,顺序无关紧要,而且散列大小将是固定的,而不是随着集合的大小而增长。

使用内置 java 字符串哈希码的哈希码:

int hashcode = strings.stream()
        .mapToInt(Object::hashCode)
        .reduce(0, (left, right) -> left ^ right);

Hashcode using guava and MD5 like the question:

Optional<byte[]> hash = strings.stream()
        .map(s -> Hashing.md5().hashString(s, Charset.defaultCharset()))
        .map(HashCode::asBytes)
        .reduce((left, right) -> xor(left, right));


static byte[] xor(byte[] left, byte[] right) {
    if(left.length != right.length) {
        throw new IllegalArgumentException();
    }
    byte[] result = new byte[left.length];
    for(int i=0; i < result.length; i++) {
        result[i] = (byte) (left[i] ^ right[i]);
    }
    return result;
}

【讨论】:

  • 这是首选方法。对哈希进行异或比添加它们更好。
  • 是的,这对于 sets 是正确的,但是对于可以包含重复的 bags XOR 不适用,因为重复会将其重置为零 @LukeJoshuaPark,所以必须使用一些SUM(已包装)。
【解决方案2】:

您可以单独计算每个字符串的 MD5 哈希值,然后将它们全部相加得到一个哈希值。这将与订单无关。因为加法运算是可交换的。

这是一个示例(假设我们有一个方法 md5Hex(String str) 计算给定字符串的 md5 哈希值并以十六进制格式返回结果):

String[] strings = {"str1", "str2", "str3", ...};

BigInteger hashSum = BigInteger.ZERO;
for(String s : strings) {
    String hexHash = md5Hex(s);
    hashSum = hashSum.add(new BigInteger(hexHash, 16));
}

String finalHash = hashSum.toString(16);

【讨论】:

  • 好的,谢谢;问题的背景(虽然被低估了)是我是否应该这样做或使用一些可以结合未排序和可能接收更少冲突的替代哈希算法。
  • @MarmiteBomber,添加了一个示例。
猜你喜欢
  • 2018-04-05
  • 2013-08-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多