1. 程式人生 > >從解析String的hashCode和equals方法原始碼到hash衝突

從解析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; }
hashcode
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; }
equals

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個字串內容是否一致嚴格上是錯誤的。