想要明白hashCode的做用,你必需要先知道Java中的集合。java
總的來講,Java中的集合(Collection)有兩類,一類是List,再有一類是Set。 算法
你知道它們的區別嗎?前者集合內的元素是有序的,元素能夠重複;後者元素無序,但元素不可重複。 數據結構
那麼這裏就有一個比較嚴重的問題了:要想保證元素不重複,可兩個元素是否重複應該依據什麼來判斷呢?
這就是Object.equals方法了。可是,若是每增長一個元素就檢查一次,那麼當元素不少時,後添加到集合中的元素比較的次數就很是多了。
也就是說,若是集合中如今已經有1000個元素,那麼第1001個元素加入集合時,它就要調用1000次equals方法。這顯然會大大下降效率。
因而,Java採用了哈希表的原理。哈希(Hash)其實是我的名,因爲他提出一哈希算法的概念,因此就以他的名字命名了。
哈希算法也稱爲散列算法,是將數據依特定算法直接指定到一個地址上。若是詳細講解哈希算法,那須要更多的文章篇幅,我在這裏就不介紹了。
初學者能夠這樣理解,hashCode方法實際上返回的就是對象存儲的物理地址(實際可能並非)。
這樣一來,當集合要添加新的元素時,先調用這個元素的hashCode方法,就一會兒能定位到它應該放置的物理位置上。
若是這個位置上沒有元素,它就能夠直接存儲在這個位置上,不用再進行任何比較了;若是這個位置上已經有元素了,
就調用它的equals方法與新元素進行比較,相同的話就不存了,不相同就散列其它的地址。 this
因此這裏存在一個衝突解決的問題。這樣一來實際調用equals方法的次數就大大下降了,幾乎只須要一兩次。spa
因此,Java對於eqauls方法和hashCode方法是這樣規定的: .net
一、若是兩個對象相同,那麼它們的hashCode值必定要相同;二、若是兩個對象的hashCode相同,它們並不必定相同 上面說的對象相同指的是用eqauls方法比較。 3d
你固然能夠不按要求去作了,但你會發現,相同的對象能夠出如今Set集合中。同時,增長新元素的效率會大大降低。code
根據官方文檔的定義,咱們能夠抽出成以對象
下幾個關鍵點:排序
一、hashCode的存在主要是用於查找的快捷性,如Hashtable,HashMap等,hashCode是用來在散列存儲結構中肯定對象的存儲地址的;
二、若是兩個對象相同,就是適用於equals(Java.lang.Object) 方法,那麼這兩個對象的hashCode必定要相同;
三、若是對象的equals方法被重寫,那麼對象的hashCode也儘可能重寫,而且產生hashCode使用的對象,必定要和equals方法中使用的一致,不然就會違反上面提到的第2點;
四、兩個對象的hashCode相同,並不必定表示兩個對象就相同,也就是不必定適用於equals(java.lang.Object) 方法,只可以說明這兩個對象在散列存儲結構中,如Hashtable,他們「存放在同一個籃子裏」。
再概括一下就是hashCode是用於查找使用的,而equals是用於比較兩個對象的是否相等的。
如下這段話是從別人帖子回覆拷貝過來的:
如下這段話是從別人帖子回覆拷貝過來的:
這是輸出結果:
以上這個示例,咱們只是重寫了hashCode方法,從上面的結果能夠看出,雖然兩個對象的hashCode相等,可是實際上兩個對象並非相等;,咱們沒有重寫equals方法,那麼就會調用object默認的equals方法,是比較兩個對象的引用是否是相同,顯示這是兩個不一樣的對象,兩個對象的引用確定是不定的。這裏咱們將生成的對象放到了HashSet中,而HashSet中只可以存放惟一的對象,也就是相同的(適用於equals方法)的對象只會存放一個,可是這裏其實是兩個對象a,b都被放到了HashSet中,這樣HashSet就失去了他自己的意義了。
此時咱們把equals方法給加上:
此時獲得的結果就會以下:
從結果咱們能夠看出,如今兩個對象就徹底相等了,HashSet中也只存放了一份對象。