覆寫hashCode

在比較兩個實例是否相等的時候,一般會覆寫equal()方法,而後對類對象的每一成員進行逐一比較,可是JavaSE6規範以下:java

  • 應用程序的執行期間,只要對象的equals方法的比較操做所用到的信息沒有被修改,那麼對這同一個對象調用屢次,hashCode方法都必須始終如一地返回同一個整數。在同一個應用程序的屢次執行過程當中,每次執行所返回的整數能夠不一致。數組

  • 若是兩個對象根據equals()方法比較是相等的,那麼調用這兩個對象中任意一個對象的hashCode方法都必須產生一樣的整數結果。ide

若是調用父類的equal()方法,且x.equal(y)返回值是true,返回的hashCode值卻不一樣,所以在覆寫equal()方法的同時覆寫hashCode()方法。這樣才能最大限度地保證,在程序運行過程當中儘量少的出現莫名其妙的錯誤。函數

再此以前咱們先看一下String類中的hashCode()方法:學習

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()方法返回的是一個int類型的值,難道這就是所謂的hashCode?不要急,咱們來看一段話,code

一個好的散列函數一般傾向於「爲不相等的對象產生不相等的散列碼」
對於對象中的每一個關鍵域f(指equal方法中涉及的每一個域),完成如下步驟:對象

  • 若是該域是boolean類型,則計算(f?1:0);遞歸

  • 若是該域是byte、char、short或者int計算(int)f;字符串

  • 若是該域是long型,計算(int)(f^(f>>>32));get

  • 若是該域是float類型,計算Float.floatTOIntBits(f);

  • 若是該域是double類型,計算Double.doubleToLongBits(f),而後再根據long型計算獲得散列值;

  • 若是該域是一個引用對象,而且該類的equal方法經過遞歸調用equal的方法來比較這個域,則一樣爲這個域遞歸調用hashCode,若是這個域爲空,則返回0;
    -若是該域是一個數組,則要把每個元素看成單獨的域來處理

按照下面的公式,把上面計算獲得的散列碼c合併到result中

  • result=31*result+c;

--------------摘自Effective Java

這是EffectiveJava中給出的計算散列碼的方法,固然,方法並非惟一,只要咱們保證相同的對象會產生相同的散列碼,不一樣的得到的散列碼不一樣就能夠了。

如今咱們回過頭來看看String類中的hashCode方法

public int hashCode() {
        int h = hash;
        if (h == 0 && value.length > 0) {//判斷hash值不爲0,字符串不爲空(即長度大於0)
            char val[] = value;//將字符串的值轉化爲char型數組
            for (int i = 0; i < value.length; i++) {
                h = 31 * h + val[i];//遍歷char數組中的每個元素經過計算獲得hash值
            }
            hash = h;
        }
        return h;
    }

看到這裏相信你們已經明瞭,hash散列碼的意義所在,
這裏咱們給出一段三個域都是int的hash值計算實例

@Override
    public int hashCode() {
        int result = hashCode;
        //生成對象的惟一散列碼
        if (result == 0) {
            result = result * 31 + areaCode;
            result = result * 31 + prefix;
            result = result * 31 + lineNumber;
            hashCode=result;
        }
        return hashCode;
    }

最後,若是你們想深刻學習java的話,建議你們看一看effective java,相信會收穫頗豐的。

更多關於java的文章請戳這裏:(您的留言意見是對我最大的支持)

個人文章列表

Email:sxh13208803520@gmail.com

相關文章
相關標籤/搜索