我正在尝试实现一个函数来生成在 node.js 和 python 中等效的 java hashCode 以实现 redis 分片。我正在关注非常好的博客 @below 提到的链接来实现这一点 http://mechanics.flite.com/blog/2013/06/27/sharding-redis/
但是如果字符串包含一些不是 ascii 的字符,我就会卡在 hashCode 的差异上,如下例所示。对于常规字符串,我可以获得 node.js 和 python 给我相同的哈希码。
这是我用来生成这个的代码:
-- python
def _java_hashcode(s):
hash_code = 0
for char in s:
hash_code = 31*h + ord(char)
return ctypes.c_int32(h).value
-- Node 如上博客
String.prototype.hashCode = function() {
for(var ret = 0, i = 0, len = this.length; i < len; i++) {
ret = (31 * ret + this.charCodeAt(i)) << 0;
}
return ret;
};
--Python输出
For string '者:s��2�*�=x�' hash is = 2014651066
For string '359196048149234' hash is = 1145341990
-- Node 输出
For string '者:s��2�*�=x�' hash is = 150370768
For string '359196048149234' hash is = 1145341990
请指导我,我在哪里弄错了..我是否需要在 python 和 Node 程序中设置某种类型的编码,我尝试了一些但我的程序在 python 中中断。
最佳答案
def java_string_hashcode(s):
"""Mimic Java's hashCode in python 2"""
try:
s = unicode(s)
except:
try:
s = unicode(s.decode('utf8'))
except:
raise Exception("Please enter a unicode type string or utf8 bytestring.")
h = 0
for c in s:
h = int((((31 * h + ord(c)) ^ 0x80000000) & 0xFFFFFFFF) - 0x80000000)
return h
这就是你在 python 2 中应该做的。
问题有两个:
- 您应该使用 unicode 类型,并确保它是这样。
- 在每一步之后,您需要防止 python 自动转换为 long 类型,方法是使用按位运算为后续步骤获取正确的 int 类型。 (交换符号位,屏蔽为 32 位,然后减去符号位的数量,如果符号位存在则为负 int,如果符号位不存在则为正 int。这模仿了 Java 中的 int 行为.
此外,与其他答案一样,对于硬编码的非 ascii 字符,请将源文件保存为 utf8 并在文件顶部写入:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
并确保如果您收到用户输入,您将它们作为 unicode 类型而不是字符串类型处理。 (对于 python 3 不是问题)
关于javascript - 在 python 和 node.js 中复制 java.lang.String.hashCode() 输出的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22845913/