Zero-Allocation-Hashing的murmur3中hashChars与hashBytes输出差异及对齐Guava方法
OpenHFT Zero-Allocation-Hashing Murmur3 使用问题解答
问题描述
在使用OpenHFT Zero-Allocation-Hashing 0.16版本的Murmur3算法时,发现hashChars()和hashBytes()输出结果不同:
// Using zero-allocation-hashing 0.16 String input = "abc123"; System.out.println(LongHashFunction.murmur_3().hashChars(input)); System.out.println(LongHashFunction.murmur_3().hashBytes(input.getBytes(StandardCharsets.UTF_8)));
输出结果:
-4878457159164508227 -7432123028918728600
其中hashBytes()的输出与Guava库结果一致。请问:
- 针对String输入应使用哪个函数?为何两个函数结果不同?
- 如何使用Zero-Allocation-Hashing库得到与以下Guava代码相同的输出?
Hashing.murmur3_128().newHasher().putString(input, Charsets.UTF_8).hash().asLong(); Hashing.murmur3_128().newHasher().putString(input, Charsets.UTF_8).hash().toString()
解答
1. String输入的函数选择与结果差异原因
- 函数选择:如果需要和Guava的哈希结果对齐,应该使用
hashBytes(input.getBytes(StandardCharsets.UTF_8))。 - 差异原因:
hashChars()直接处理Java字符串的底层char[]数组,Java的char采用UTF-16编码,每个字符占2字节(ASCII字符的高位字节为0)。hashBytes()处理的是字符串转成UTF-8编码后的字节数组,ASCII字符在UTF-8中仅占1字节。
两者输入的原始字节序列完全不同,因此Murmur3算法计算出的哈希值自然不一致。
2. 对齐Guava 128位Murmur3输出的实现
Guava的Hashing.murmur3_128()是128位版本的Murmur3哈希,对应Zero-Allocation-Hashing中的LongHashFunction.murmur_3_128(),以下是对齐实现:
对应asLong()的输出
Guava的asLong()返回128位哈希值的低64位,Zero-Allocation-Hashing中可通过LongPair.lowerLong()获取:
String input = "abc123"; byte[] utf8Bytes = input.getBytes(StandardCharsets.UTF_8); LongPair hashPair = LongHashFunction.murmur_3_128().hashBytes(utf8Bytes); long result = hashPair.lowerLong(); System.out.println(result); // 与Guava的asLong()结果一致
对应toString()的输出
Guava的hash().toString()返回32位全大写十六进制字符串(128位哈希的完整表示),可通过拼接LongPair两个long值的十六进制字符串实现:
String input = "abc123"; byte[] utf8Bytes = input.getBytes(StandardCharsets.UTF_8); LongPair hashPair = LongHashFunction.murmur_3_128().hashBytes(utf8Bytes); // 补全前导零并转大写,拼接高位和低位哈希值 String hexStr = String.format("%016X%016X", hashPair.upperLong(), hashPair.lowerLong()); System.out.println(hexStr); // 与Guava的toString()结果一致
内容的提问来源于stack exchange,提问作者Nishant Kumar
相关产品推荐
相关产品推荐

