从解析String的hashCode和equals方法源码到hash冲突
经常被问到hashcode方法和equals方法还有== ,网上都有结论,但我们不能知其然却不知其所以然。所以我们从string的hashcode和equals入手,探究这3者,先贴源码。
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; }
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; }
1.string的hashcode主要代码 h = 31 * h + val[i];
遍历所有字符,val[i]对应ASCII表中的值,将它与h*31累加。最终得出一个hash值,但我们可以从这个算法得知,不同的字符串有可能得出相同的hashcode值(概率很低)
比如2个val1[1,0];val2[31]; 我这里直接将ASCII值代替进去了,它们运算后的h都是31,但它们代表的内容不同。
所以通过hashcode值判断2个字符串是否相等是不行的。
2.equals方法.
== : 它的作用是判断两个对象的地址是不是相等
equals方法先判断2个字符串==,假如2个字符串都==了,就是同一个对象了,肯定就相等了。
然后遍历2个字符串,一一对应比较字符,假如都相等了,就说这2个字符串内容一样。
总结:equals方法比较了2个字符串是否是同一个对象,并且比较它们的内容是否一样。
如果是同一个对象那么内容肯定一致,根据hashcode算法它们的hash值也一样,
不同对象,它们内容也可能一致,内容一致hash值也就一样,
但是内容和对象都不一样,它们的hash值有可能相同,这样就出现了所谓的hash冲突。原因取决于hashcode的算法(见1)
所以通过hash值来比较2个字符串内容是否一致严格上是错误的。