Java中String类hashCode()和equals()问题
在网络上看到一个有趣的问题:能否定义两个字符串s1和s2对象,使得以下结论同时成立:1. s1.equals(s2) 得到的结果是false;2. s1.hashCode() == s2.hashCode() 得到的结果是true 。
查看String中hashCode()方法的定义如下:
public int hashCode() {
int hash = hashCode;
if (hash == 0) {
if (count == 0) {
return 0;
}
final int end = count + offset;
final char[] chars = value;
for (int i = offset; i < end; ++i) {
hash = 31*hash + chars[i];
}
hashCode = hash;
}
return hash;
}
String类中hashCode()方法的实质是,形如"abcde"这样的字串的hashCode为a*31^4+b*31^3+c*31^2+d*31+e。因此要想s1和s2字串不一样,同时s1和s2的hashCode相等。我们可以假设s1和s2的长度均为2,于是可以构造一个字串出来:
s1=ab; // (a,b 未知)
s2=cd; // (c,d 未知)
s1和s2满足条件: a*31+b = c*31+d, 且 a,b,c,d均小于128; 于是 (a-c)*31 = d-b。查ASCII码表可以随便得出一个s1和s2的字串出来:
s1="BE";
s2="Ae";
public static void main(String[] args) {
// TODO Auto-generated method stub
String s1 = "BE";
String s2 = "Ad";
boolean b1 = s1.equals(s2);
boolean b2 = (s1.hashCode() == s2.hashCode());
System.out.println("s1.equals(s2):"+b1+"\n"
+"s1.hashCode():"+s1.hashCode()+", s2.hashCode():"+s2.hashCode()+"\n"
+"s1.hashCode() == s2.hashCode():"+b2);
}
运行结果为:
s1.equals(s2):false
s1.hashCode():2115, s2.hashCode():2115
s1.hashCode() == s2.hashCode():true
或者s1=""; s2="\u0000"; s1.equals(s2) = false; s1.hashCode() == s2.hashCode() .
所以,存在字串s1和s2,equals为false,hashCode为true。那么String类的hashCode()方法作用是什么呢?Android官网说明为:
“Returns an integer hash code for this object. By contract, any two objects for whichequals(Object)
returnstrue
must return the same hash code value. This means that subclasses ofObject
usually override both methods or neither method.”
即s1.equals(s2) 为true的话,那么s1.hashCode() 一定等于 s2.hashCode()。反之,如果s1.hashCode 不等于 s2.hashCode()的话,那么s1和s2一定不相等。这就是我对hashCode()作用的理解。在实践中,我们可以利用推理“如果s1.hashCode 不等于 s2.hashCode()的话,那么s1和s2一定不相等。” 来干很多事。网上有人对hashCode()做了这样的解释:
以java.lang.Object来理解,JVM每new一个Object,它都会将这个Object丢到一个Hash哈希表中去,这样的话,下次做Object的比较或者取这个对象的时候,它会根据对象的hashcode再从Hash表中取这个对象。这样做的目的是提高取对象的效率。具体过程是这样:
1.new Object(),JVM根据这个对象的Hashcode值,放入到对应的Hash表对应的Key上,如果不同的对象确产生了相同的hash值,也就是发生了Hash key相同导致冲突的情况,那么就在这个Hash key的地方产生一个链表,将所有产生相同hashcode的对象放到这个单链表上去,串在一起。
2.比较两个对象的时候,首先根据他们的hashcode去hash表中找他的对象,当两个对象的hashcode相同,那么就是说他们这两个对象放在Hash表中的同一个key上,那么他们一定在这个key上的链表上。那么此时就只能根据Object的equal方法来比较这个对象是否equal。当两个对象的hashcode不同的话,肯定他们不能equal.
具体请参考原文:《hashCode的作用》