我正在尝试使用Murmur3算法生成散列。散列是一致的,但它们是Scala和Guava返回的不同值。
class package$Test extends FunSuite {
test("Generate hashes") {
println(s"Seed = ${MurmurHash3.stringSeed}")
val vs = Set("abc", "test", "bucket", 111.toString)
vs.foreach { x =>
println(s"[SCALA] Hash for $x = ${MurmurHash3.stringHash(x).abs % 1000}")
println(s"[GUAVA] Hash for $x = ${Hashing.murmur3_32().hashString(x).asInt().abs % 1000}")
println(s"[GUAVA with seed] Hash for $x = ${Hashing.murmur3_32(MurmurHash3.stringSeed).hashString(x).asInt().abs % 1000}")
println()
}
}
}
Seed = -137723950
[SCALA] Hash for abc = 174
[GUAVA] Hash for abc = 419
[GUAVA with seed] Hash for abc = 195
[SCALA] Hash for test = 588
[GUAVA] Hash for test = 292
[GUAVA with seed] Hash for test = 714
[SCALA] Hash for bucket = 413
[GUAVA] Hash for bucket = 22
[GUAVA with seed] Hash for bucket = 414
[SCALA] Hash for 111 = 250
[GUAVA] Hash for 111 = 317
[GUAVA with seed] Hash for 111 = 958为什么我会得到不同的哈希?
发布于 2015-05-12 16:43:08
在我看来,Scala的hashString将UTF-16 chars转换成与番石榴的hashUnencodedChars不同的UTF-16hashUnencodedChars(没有Charset的hashString被重命名为hashUnencodedChars)。
Scala:
val data = (str.charAt(i) << 16) + str.charAt(i + 1)番石榴:
int k1 = input.charAt(i - 1) | (input.charAt(i) << 16);在番石榴中,索引char中的i成为int中最不重要的16位,而i + 1上的char则成为最重要的16位。在Scala实现中,情况正好相反:char at i是最重要的,而char at i + 1是最不重要的。(我认为Scala实现使用+而不是|也很重要。)
请注意,番石榴实现相当于两次使用ByteBuffer.putChar(c)将两个字符放入一个小的endian ByteBuffer中,然后使用ByteBuffer.getInt()返回一个int值。番石榴实现还相当于使用UTF-16LE将字符编码为字节并对这些字节进行散列。Scala实现不等同于在JVM需要支持的任何标准字符集中编码字符串。一般来说,我不确定Scala有什么先例(如果有的话)。
编辑:
Scala实现还做了与Guava实现不同的事情:它将散列的字符数传递给finalizeHash方法,其中Guava的实现将字节数传递给等效的fmix方法。
发布于 2015-05-12 17:00:52
我认为hashString(x, StandardCharsets.UTF_16BE)应该与Scala的行为相匹配。让我们知道。
(另外,请把番石榴升级到新的!)
https://stackoverflow.com/questions/30196298
复制相似问题