字符串的哈希码在整个应用程序中是否相同?

5
我正在开发一个基于哈希的程序。 我的问题是,一个字符串的HashCode在整个应用程序中是否会保持不变。
我之所以问这个问题,是因为Memcached服务器内的KetamaMemcachedSessionLocator是这样工作的: 如果有两个运行着Memcache的服务器,我想要从特定的服务器定位一个键。
String key = "MyString";
int keyid = key.hashCode();
int v = keyid % 1;  //( I assume that this will contact the First Server to retrieve that value )
int v = keyid % 2;  //( I assume that this will contact the Second Server to retrieve that value )
String value = MemcachedClient.get(key, v);

根据这个网站的说明,可以按照以下步骤实施:

http://dev.mysql.com/doc/refman/5.0/en/ha-memcached-using-hashtypes.html

如果您发现上述方式有任何问题,请分享您的意见。

2个回答

10
根据哈希码约定,如果string1.eqauls(string2),则它们的哈希码始终相同。 java.lang.String哈希函数 为了提供快速实现,Java String类的早期版本提供了一个hashCode()实现,该实现最多考虑了从字符串中选择的16个字符。对于一些常见数据,这种方法效果非常差,导致结果聚集严重,因此散列表性能慢。
从Java 1.2开始,java.lang.String类使用整个字符串文本上的乘积和算法来实现其hashCode()。例如,java.lang.String类的实例s将由哈希码h(s)定义。

h(s)=\sum_{i=0}^{n-1}s[i] \cdot 31^{n-1-i}

其中使用Java 32位整数加法对术语进行求和,s [i]表示字符串的第i个字符,n是s的长度。

与任何通用哈希函数一样,碰撞是可能的。例如,字符串“FB”和“Ea”具有相同的哈希值。String的hashCode()实现使用质数31和'a'和'B'之间的差仅为31,因此计算为70×31 + 66 = 69×31 + 97。

检查Java SE 7中的集合框架增强功能,因为您会发现其中有更改,而且谁知道将会有哪些。

备选哈希函数仅适用于String类型的键。


这里不会出现碰撞问题,我正在使用Java 1.6,未来几年我们不会更改Java版本,所以我会采用这种方法。谢谢。 - Pawan

1

是和不是。

hashCode()协议规定,在同一JVM中,两个相等的字符串将具有相同的哈希码。这意味着只要字符串不改变,代码就不会改变。

另一方面,实际的hashCode()实现从一个JVM版本到另一个JVM版本和/或从一个JVM供应商到另一个JVM供应商已经发生了变化。例如,Oracle Java 7u6提供了一种更快的替代哈希函数,用于超过某个大小的字符串。目前它仅在集合框架中使用,但它很可能成为Java 8的系统范围默认值。

基本上,您可以依赖于hashCode()在同一应用程序中保持一致,但不能在不同的应用程序实例之间保持一致。如果您打算存储或共享哈希码,则应该自己实现函数。

另一个可能感兴趣的点是,Java中定义的hashCode()是一个32位长的int。这绝不是一个唯一标识符——冲突非常频繁,程序员需要处理它们。如果您的存储系统依赖于唯一键,您可能希望使用更强的哈希函数,例如SHA-2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接