在Python和Node.js中复现java.lang.String.hashCode()输出的函数
我正在尝试在 Node.js 和 Python 中实现一个函数,用来生成与 Java 的 hashCode 相同的值,以便进行 Redis 分片。我在参考一篇很不错的博客,链接在这里:http://mechanics.flite.com/blog/2013/06/27/sharding-redis/
但是我遇到了一个问题,就是当字符串中包含一些非 ASCII 字符时,hashCode 的计算结果会有所不同。对于普通字符串,我可以得到 Node.js 和 Python 都给出相同的 hashCode。
这是我用来生成 hashCode 的代码:
--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.js 代码
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 程序就出错了。
2 个回答
0
在Python 2中,如果不特别说明,它会默认使用ASCII编码。自从有了PEP 0263这个规范后,你可以在文件的顶部添加以下内容来指定使用utf-8编码的字符串。
#!/usr/bin/python
# -*- coding: utf-8 -*-
12
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自动把数据转换成长整型。可以通过位运算来获取正确的整型,以便进行下一步操作。(通过交换符号位、掩码到32位,然后减去符号位的值,如果符号位存在,就会得到一个负数,如果符号位不存在,就会得到一个正数。这种方式模仿了Java中的整型行为。)
另外,正如其他回答所提到的,对于硬编码的非ASCII字符,请将你的源文件保存为utf8格式,并在文件顶部写上:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
确保如果你接收到用户输入,要把它们处理为unicode类型,而不是字符串类型。(在Python 3中这不是问题)