Murmur3在Python和Java实现之间散列不同的结果

时间:2015-04-29 01:47:30

标签: java python guava murmurhash

我有两个不同的程序希望分别使用Python和Java中的Murmur3来散列相同的字符串。

Python版本2.7.9:

mmh3.hash128('abc')

给予79267961763742113019008347020647561319L。

Java是Guava 18.0:

HashCode hashCode = Hashing.murmur3_128().newHasher().putString("abc", StandardCharsets.UTF_8).hash();

提供字符串" 6778ad3f3f3f96b4522dca264174a23b",转换为BigInterger给出137537073056680613988840834069010096699。

如何从两者获得相同的结果?

由于

2 个答案:

答案 0 :(得分:6)

以下是如何从两者获得相同的结果:

byte[] mm3_le = Hashing.murmur3_128().hashString("abc", UTF_8).asBytes();
byte[] mm3_be = Bytes.toArray(Lists.reverse(Bytes.asList(mm3_le)));
assertEquals("79267961763742113019008347020647561319",
    new BigInteger(mm3_be).toString());

哈希码的字节需要被视为 little endian ,但BigInteger将字节解释为大端。您可能使用new BigInteger(hex, 16)来创建BigInteger,但HashCode.toString()的输出实际上是一系列十六进制数字对,表示它们返回的相同顺序的哈希字节由asBytes()(小端)。 (您也可以反转这些十六进制对,以获得一个十六进制数,当传递给new BigInteger(reversedHex, 16)时,它会产生相同的结果。)

我认为toString()的文档有点令人困惑,因为它引用的方式是" big endian&#34 ;;它实际上并不意味着该方法的输出是十六进制数,表示被解释为大端的字节。

我们有一个开放issue用于将asBigInteger()添加到HashCode

答案 1 :(得分:0)

如果有人对反向答案感兴趣,请将python输出转换为Java输出:

import mmh3
import string

char_array = '0123456789abcdef'
mumrmur = mmh3.hash_bytes('abc')

result = [f'{string.hexdigits[(char >> 4) & 0xf]}{string.hexdigits[char & 0xf]}' for char in mumrmur]
print(''.join(result))