對HashCode的記錄學習
一、hashcode是什麽?
1、hash和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的功能就是 “==”號的功能。
對HashCode的記錄學習