Java中的hashCode方法就是根據必定的規則將與對象相關的信息(好比對象的存儲地址,對象的字段等)映射成一個數值,這個數值稱做爲散列值,即hashCode值.html
在Java的Object類中有一個方法:java
public native int hashCode();
根據這個方法的聲明可知,該方法返回一個int類型的數值,而且是本地方法,所以在Object類中並無給出具體的實現。算法
有些朋友誤覺得默認狀況下,hashCode返回的就是對象的存儲地址,事實上這種見解是不全面的,確實有些JVM在實現時是直接返回對象的存儲地址,可是大多時候並非這樣,只能說可能存儲地址有必定關聯。數組
hashCode返回的並不必定是對象的(虛擬)內存地址,具體取決於運行時庫和JVM的具體實現性能
在Java中hashCode的實現老是伴隨着equals,他們是緊密配合的,你要是本身設計了其中一個,就要設計另一個。固然在多數狀況下,這兩個方法是不用咱們考慮的,直接使用默認方法就能夠幫助咱們解決不少問題。可是在有些狀況,咱們必需要本身動手來實現它,才能確保程序更好的運做。this
對於equals,咱們必須遵循以下規則:spa
對稱性:若是x.equals(y)返回是「true」,那麼y.equals(x)也應該返回是「true」。設計
反射性:x.equals(x)必須返回是「true」。code
類推性:若是x.equals(y)返回是「true」,並且y.equals(z)返回是「true」,那麼z.equals(x)也應該返回是「true」。htm
一致性:若是x.equals(y)返回是「true」,只要x和y內容一直不變,無論你重複x.equals(y)多少次,返回都是「true」。
任何狀況下,x.equals(null),永遠返回是「false」;x.equals(和x不一樣類型的對象)永遠返回是「false」。
對於hashCode,咱們應該遵循以下規則:
1. 在一個應用程序執行期間,若是一個對象的equals方法作比較所用到的信息沒有被修改的話,則對該對象調用hashCode方法屢次,它必須始終如一地返回同一個整數。
2. 若是兩個對象根據equals(Object o)方法是相等的,則調用這兩個對象中任一對象的hashCode方法必須產生相同的整數結果。
3. 若是兩個對象根據equals(Object o)方法是不相等的,則調用這兩個對象中任一個對象的hashCode方法,不要求產生不一樣的整數結果。但若是能不一樣,則可能提升散列表的性能。
根據hashCode,equals所遵循的規則咱們不可貴出:
若是x.equals(y)返回「true」,那麼x和y的hashCode()必須相等。
若是x.equals(y)返回「false」,那麼x和y的hashCode()有可能相等,也有可能不等。
能夠用一張流程圖來描述 hashCode,equals是如何配合使用
`
整個處理流程是:
一、判斷兩個對象的hashcode是否相等,若不等,則認爲兩個對象不等,完畢,若相等,則比較equals。
二、若兩個對象的equals不等,則能夠認爲兩個對象不等,不然認爲他們相等。
對於包含容器類型的程序設計語言來講,基本上都會涉及到hashCode。在Java中也同樣,hashCode方法的主要做用是爲了配合基於散列的集合一塊兒正常運行,提升查找效率.這樣的散列集合包括HashSet、HashMap以及HashTable
實際場景:當向集合中插入對象時,如何判別在集合中是否已經存在該對象了?(注意:集合中不容許重複的元素存在如Set集合)
解決辦法:採用equals方法去逐一比較,效率必然是一個問題.此時就須要用hashcode和equals配置使用提升效率
根據第二章節hashcode,equals所遵循的規則以及配合使用的流程.
當集合要添加新的對象時,先調用這個對象的hashCode方法,獲得對應的hashcode值,實際上在HashMap的具體實現中會用一個table保存已經存進去的對象的hashcode值
1. 若是table中沒有該hashcode值,即第一步的判斷 hashcode是否相同結果爲false ,表示沒有與該對象相等的對象.它就能夠直接存進去,不用再進行任何比較了
2.若是存在該hashcode值,進行第二步equals判斷(由於根據hashcode規則不一樣對象可能具備相同的hashcode值),若是爲true即對象相等,存在該對象就不保存.反之false不存在保存.
下面這段代碼是java.util.HashMap的中put方法的具體實現:
public V put(K key, V value) { if (key == null) return putForNullKey(value); int hash = hash(key.hashCode()); int i = indexFor(hash, table.length); for (Entry<K,V> e = table[i]; e != null; e = e.next) { Object k; if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } } modCount++; addEntry(hash, key, value, i); return null; }
hashCode重要麼?不重要,對於List集合、數組而言,他就是一個累贅,可是對於HashMap、HashSet、HashTable而言,它變得異常重要。因此在使用HashMap、HashSet、HashTable時必定要注意hashCode。對於一個對象而言,其hashCode過程就是一個簡單的Hash算法的實現,其實現過程對你實現對象的存取過程起到很是重要的做用。