问题铺垫
hotspot jdk1.8
:
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
/**
* Returns a hash code for this string. The hash code for a
* {@code String} object is computed as
* <blockquote><pre>
* s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
* </pre></blockquote>
* using {@code int} arithmetic, where {@code s[i]} is the
* <i>i</i>th character of the string, {@code n} is the length of
* the string, and {@code ^} indicates exponentiation.
* (The hash value of the empty string is zero.)
*
* @return a hash code value for this object.
*/
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}
tips:
h = 31 * h + val[i];
这里的实际上是整形和字符相加,也就是和字符的对应的 unicode 编码码值或者保留值(高代理区和低代理区)相加(范围即 0-65535,这里可能与是否超过 BMP 无关(代理区模式))
hashcode和equals满足如下条件:
1. equals() 相等的两个对象他们的 hashCode() 肯定相等
2. equals() 不相等的两个对象, hashcode() 有可能相等
3. hashCode() 相等的两个对象他们的 equals() 不一定相等
4. hashcode() 不等,一定能推出 equals() 也不等
我们知道,String 类对 hashcode 和 equals 进行了覆写,相同字符串的值的 equals() 才会相等,当然此时 hashcode 也是相等的 (这里满足了1).
不同字符串值的 hashcode 也可能相等 ( hash 冲突)(这里符合2).
问题
我想问的是 (这也许是个数学问题):
- 条件3冲突的概率? s[0]31^(n-1) + s[1]31^(n-2) + ... + s[n-1]
- 如何证明String类符合4?
1、字符串的长度虽然有理论的最大值,但是在这个问题里可以按无限来算,而且你没给定源字符串的范围,在此基础上,可以认为hashCode为1~Integer.INT_MAX之间任意的值都有可能。相等的概率自然是1/Integer.INT_MAX。考虑到具体情况,如果输入字符串里有大量的短串,比如"abc" "ac" "mmm"之类,哈希码可能会集中在一个范围。
2、把字符串看作数列A,另外定义一个数列B:
规定B(1) = 31 * A(1)
对于任意大于1的正整数n,B(n) = 31 * B(n-1) + A(n)
用数学归纳法就能知道,A只能得到唯一的B(n)。