hashcode詳解

一杯涼茶發表於2016-11-16

      序言

         寫這篇文章是因為在看hashMap原始碼時遇到有什麼hashcode值,然後就去查,腦袋裡面是有映像的,不就是在Object中有equals和hashcode方法嘛,這在學java基礎的時候就遇到過,不過那時候無所謂,不懂就不懂,就一筆帶過去了,然後到現在,又回過頭來補本應該以前就搞清楚的問題,所以知道了一個道理,學習不是一個追求速度的事情,不懂就要去查清楚,弄明白,一步一個腳印,雖然剛開始可能會很慢,不過慢慢的,學習的多了,理解的多了,會越來越快的。越來越輕鬆,不至於現在還在補原來的知識。後悔也無事於補了,起碼現在知道了這個道理,學習永遠都不會遲,只要突然一天的醒悟,一切都會慢慢好起來的。  

          弄懂這知識點,查了很多博文,發現很多類似,我不知道哪個才是原著,所以複製一個我覺得比較好的,不過看了也有些迷惑,我會寫下來。

            http://blog.csdn.net/zhangyuan19880606/article/details/51240372

                                                                            ---WH

    

一、hashcode是什麼?

   1、hash和hash表是什麼?   

      想要知道這個hashcode,首先得知道hash,通過百度百科看一下

              

                

      hash是一個函式,該函式中的實現就是一種演算法,就是通過一系列的演算法來得到一個hash值,這個時候,我們就需要知道另一個東西,hash表,通過hash演算法得到的hash值就在這張hash表中,也就是說,hash表就是所有的hash值組成的,有很多種hash函式,也就代表著有很多種演算法得到hash值,如上面截圖的三種,等會我們就拿第一種來說。

 

   2、hashcode 

      有了前面的基礎,這裡講解就簡單了,hashcode就是通過hash函式得來的,通俗的說,就是通過某一種演算法得到的,hashcode就是在hash表中有對應的位置。

      每個物件都有hashcode,物件的hashcode怎麼得來的呢?

          首先一個物件肯定有實體地址,在別的博文中會hashcode說成是代表物件的地址,這裡肯定會讓讀者形成誤區,物件的實體地址跟這個hashcode地址不一樣,hashcode代表物件的地址說的是物件在hash表中的位置,實體地址說的物件存放在記憶體中的地址,那麼物件如何得到hashcode呢?通過物件的內部地址(也就是實體地址)轉換成一個整數,然後該整數通過hash函式的演算法就得到了hashcode,所以,hashcode是什麼呢?就是在hash表中對應的位置。這裡如果還不是很清楚的話,舉個例子,hash表中有 hashcode為1、hashcode為2、(...)3、4、5、6、7、8這樣八個位置,有一個物件A,A的實體地址轉換為一個整數17(這是假如),就通過直接取餘演算法,17%8=1,那麼A的hashcode就為1,且A就在hash表中1的位置。肯定會有其他疑問,接著看下面,這裡只是舉個例子來讓你們知道什麼是hashcode的意義。

 

二、hashcode有什麼作用呢?

    前面說了這麼多關於hash函式,和hashcode是怎麼得來的,還有hashcode對應的是hash表中的位置,可能大家就有疑問,為什麼hashcode不直接寫實體地址呢,還要另外用一張hash表來代表物件的地址?接下來就告訴你hashcode的作用,

    1、HashCode的存在主要是為了查詢的快捷性,HashCode是用來在雜湊儲存結構中確定物件的儲存地址的(後半句說的用hashcode來代表物件就是在hash表中的位置)

         為什麼hashcode就查詢的更快,比如:我們有一個能存放1000個數這樣大的記憶體中,在其中要存放1000個不一樣的數字,用最笨的方法,就是存一個數字,就遍歷一遍,看有沒有相同得數,當存了900個數字,開始存901個數字的時候,就需要跟900個數字進行對比,這樣就很麻煩,很是消耗時間,用hashcode來記錄物件的位置,來看一下。hash表中有1、2、3、4、5、6、7、8個位置,存第一個數,hashcode為1,該數就放在hash表中1的位置,存到100個數字,hash表中8個位置會有很多數字了,1中可能有20個數字,存101個數字時,他先查hashcode值對應的位置,假設為1,那麼就有20個數字和他的hashcode相同,他只需要跟這20個數字相比較(equals),如果每一個相同,那麼就放在1這個位置,這樣比較的次數就少了很多,實際上hash表中有很多位置,這裡只是舉例只有8個,所以比較的次數會讓你覺得也挺多的,實際上,如果hash表很大,那麼比較的次數就很少很少了。  通過對原始方法和使用hashcode方法進行對比,我們就知道了hashcode的作用,並且為什麼要使用hashcode了

 

 

三、equals方法和hashcode的關係?

     通過前面這個例子,大概可以知道,先通過hashcode來比較,如果hashcode相等,那麼就用equals方法來比較兩個物件是否相等,用個例子說明:上面說的hash表中的8個位置,就好比8個桶,每個桶裡能裝很多的物件,物件A通過hash函式演算法得到將它放到1號桶中,當然肯定有別的物件也會放到1號桶中,如果物件B也通過演算法分到了1號桶,那麼它如何識別桶中其他物件是否和它一樣呢,這時候就需要equals方法來進行篩選了。

       1、如果兩個物件equals相等,那麼這兩個物件的HashCode一定也相同

        2、如果兩個物件的HashCode相同,不代表兩個物件就相同,只能說明這兩個物件在雜湊儲存結構中,存放於同一個位置

  這兩條你們就能夠理解了。

 

四、為什麼equals方法重寫的話,建議也一起重寫hashcode方法?

      (如果物件的equals方法被重寫,那麼物件的HashCode方法也儘量重寫)

      舉個例子,其實就明白了這個道理,

        比如:有個A類重寫了equals方法,但是沒有重寫hashCode方法,看輸出結果,物件a1和物件a2使用equals方法相等,按照上面的hashcode的用法,那麼他們兩個的hashcode肯定相等,但是這裡由於沒重寫hashcode方法,他們兩個hashcode並不一樣,所以,我們在重寫了equals方法後,儘量也重寫了hashcode方法,通過一定的演算法,使他們在equals相等時,也會有相同的hashcode值。

              

 

 

    例項:現在來看一下String的原始碼中的equals方法和hashcode方法。這個類就重寫了這兩個方法,現在為什麼需要重寫這兩個方法了吧?

        equals方法:其實跟我上面寫的那個例子是一樣的原理,所以通過原始碼又知道了String的equals方法驗證的是兩個字串的值是否一樣。還有Double類也重寫了這些方法。很多類有比較這類的,都重寫了這兩個方法,因為在所有類的父類Object中。equals的功能就是 “==”號的功能。你們還可以比較String物件的equals和==的區別啦。這裡不再說明。

        

 

        hashcode方法

        

 

相關文章