寫這篇文章是因為在看hashMap源碼時很多地方遇到hashcode值。
Hash(散列函數(shù))
Hash,一般翻譯做“散列”,也有直接音譯為“哈希”的,就是把任意長度的輸入(又叫做預映射pre-image)通過散列算法變換成固定長度的輸出,該輸出就是散列值。這種轉(zhuǎn)換是一種壓縮映射,也就是,散列值的空間通常遠小于輸入的空間,不同的輸入可能會散列成相同的輸出,所以不可能從散列值來確定唯一的輸入值。簡單的說就是一種將任意長度的消息壓縮到某一固定長度的消息摘要的函數(shù)。
常用HASH函數(shù)
·直接取余法:f(x):= x mod maxM ; maxM一般是不太接近 2^t 的一個質(zhì)數(shù)。
·乘法取整法:f(x):=trunc((x/maxX)maxlongit) mod maxM,主要用于實數(shù)。
·平方取中法:f(x):=(xx div 1000 ) mod 1000000); 平方后取中間的,每位包含信息比較多。
以上來自百度百科
hashcode
我們先看看其官方定義
hashcode方法返回該對象的哈希碼值。支持該方法是為哈希表提供一些優(yōu)點,例如,java.util.Hashtable 提供的哈希表。
hashCode 的常規(guī)協(xié)定是:
在 Java 應用程序執(zhí)行期間,在同一對象上多次調(diào)用 hashCode 方法時,必須一致地返回相同的整數(shù),前提是對象上 equals 比較中所用的信息沒有被修改。從某一應用程序的一次執(zhí)行到同一應用程序的另一次執(zhí)行,該整數(shù)無需保持一致。
如果根據(jù) equals(Object) 方法,兩個對象是相等的,那么在兩個對象中的每個對象上調(diào)用 hashCode 方法都必須生成相同的整數(shù)結(jié)果。
以下情況不 是必需的:如果根據(jù) equals(java.lang.Object) 方法,兩個對象不相等,那么在兩個對象中的任一對象上調(diào)用 hashCode 方法必定會生成不同的整數(shù)結(jié)果。但是,程序員應該知道,為不相等的對象生成不同整數(shù)結(jié)果可以提高哈希表的性能。
實際上,由 Object 類定義的 hashCode 方法確實會針對不同的對象返回不同的整數(shù)。(這一般是通過將該對象的內(nèi)部地址轉(zhuǎn)換成一個整數(shù)來實現(xiàn)的,但是 JavaTM 編程語言不需要這種實現(xiàn)技巧。)
當equals方法被重寫時,通常有必要重寫 hashCode 方法,以維護 hashCode 方法的常規(guī)協(xié)定,該協(xié)定聲明相等對象必須具有相等的哈希碼。
有了前面的基礎(chǔ),這里講解就簡單了,hashcode就是通過hash函數(shù)得來的,通俗的說,就是通過某一種算法得到的,hashcode就是在hash表中有對應的位置。
每個對象都有hashcode,對象的hashcode怎么得來的呢?
首先一個對象肯定有物理地址,在別的博文中會hashcode說成是代表對象的地址,這里肯定會讓讀者形成誤區(qū),對象的物理地址跟這個hashcode地址不一樣,hashcode代表對象的地址說的是對象在hash表中的位置,物理地址說的對象存放在內(nèi)存中的地址。
那么對象如何得到hashcode呢?通過對象的內(nèi)部地址(也就是物理地址)轉(zhuǎn)換成一個整數(shù),然后該整數(shù)通過hash函數(shù)的算法就得到了hashcode,所以,hashcode是什么呢?就是在hash表中對應的位置。這里如果還不是很清楚的話,舉個例子,hash表中有 hashcode為1、hashcode為2、(...)3、4、5、6、7、8這樣八個位置,有一個對象A,A的物理地址轉(zhuǎn)換為一個整數(shù)17(這是假如),就通過直接取余算法,17%8=1,那么A的hashcode就為1,且A就在hash表中1的位置??隙〞衅渌蓡?,接著看下面,這里只是舉個例子來讓你們知道什么是hashcode的意義。
總結(jié)
從Object角度看,JVM每new一個Object,它都會將這個Object丟到一個Hash表中去,這樣的話,下次做Object的比較或者取這個對象的時候(讀取過程),它會根據(jù)對象的HashCode再從Hash表中取這個對象。這樣做的目的是提高取對象的效率。若HashCode相同再去調(diào)用equal。