1

我在 java(jedis 和 guava)、go 和 python 中尝试了三个版本的 murmurhash。java(guava)、go 和 python 版本的结果输出相同的哈希码,但与 java(jedis) 不同。所有 murmurhash 代码如下所示。我对结果感到困惑。我已经看到了这个问题Long.reverseBytes在 java 中使用,但与其他人仍然不同。那么我应该怎么做才能使 murmurhash 的所有输出保持不变。谢谢~

1.java版(绝地)

java gradlecompile group: 'redis.clients', name: 'jedis', version: '3.1.0'

import redis.clients.jedis.util.MurmurHash;

MurmurHash murmurhash = new MurmurHash();
long h = murmurhash.hash("foo");
System.out.println(h);
System.out.println(Long.reverseBytes(h));

输出:

-7063922479176959649

6897758107479832477

2.golang版本

import "github.com/spaolacci/murmur3"

foo := int64(murmur3.Sum64WithSeed([]byte("foo"), 0x1234ABCD))
fmt.Println(foo)

输出:

-5851200325189400636

3.python版

pip install mmh3

import mmh3

foo = mmh3.hash64('foo', seed=0x1234ABCD, signed=True)
print(foo)

输出:

-5851200325189400636

4.java(番石榴)

java gradlecompile group: 'com.google.guava', name: 'guava', version: '28.0-jre'

import com.google.common.hash.Hashing

long foo = Hashing.murmur3_128(0x1234ABCD).hashString("foo", charset.forName("UTF-8")).asLong();
System.out.println(foo);

输出:

-5851200325189400636
4

1 回答 1

2

TL;DR
Jedis 使用 Murmur2,而其他库使用 Murmur3。


在将一些代码从 Java/Jedis 迁移到 Golang 时,我也爱上了它。

差异是由于杂音的不同版本。直到今天,Jedis 使用 Murmur2(参见源代码文档),而上面提到的其他库使用 Murmur3。

除了查看注释/代码之外,我还使用Murmur2 参考实现验证了这一点。使用相同的种子和密钥会导致与 Jedis 示例完全相同的结果。

代码片段:

const char *key = "foo";

uint64_t result = MurmurHash64A(key, std::strlen(key), 0x1234ABCD);

std::cout << "  result (unsigned): " << result << std::endl;
std::cout << "    result (signed): " << (long) result << std::endl;
std::cout << "reversed byte order: " << __builtin_bswap64(result) << std::endl;

输出:

    result (unsigned): 11382821594532591967
      result (signed): -7063922479176959649
  reversed byte order:  6897758107479832477
于 2021-01-06T08:29:55.800 回答