哈希碼
哈希碼是一種數據結構的算法。
哈希碼具體是什麼?
答:hashCode是jdk根據對象的地址或者字符串或者數字算出來的int類型的數值
常見的哈希碼的算法有:
1:Object類的hashCode.返回對象的內存地址經過處理後的結構,由於每個對象的內存地址都不一樣,所以哈希碼也不一樣。
2:String類的hashCode.根據String類包含的字符串的內容,根據一種特殊算法返回哈希碼,只要字符串內容相同,返回的哈希碼也相同。
3:Integer類,返回的哈希碼就是Integer對象裏所包含的那個整數的數值,例如Integer i1=new Integer(100),i1.hashCode的值就是100 。
跟蹤Object類的native方法hashCode方法從jvm源碼中得到了下面的一些內容,供參考。
Object中hashCode方法是一個本地方法:public native inthashCode();
對於Java HotSpot VM,首先介紹一個概念就是對象的header,
每個對象都會有一個header,header由兩個機器字表示(8個字節對於32位架構,16個字節對於64位架構)。
header的第一個字中有7位用做同步及垃圾收集,另外25位存儲對象的hash碼。
header的第二個字存儲指向對應Class對象的指針(Class對象用來保存類的元數據信息及方法表)。
hashcode 作用 :對象實例的唯一標識
在同一運行環境下 hashcode 的值是唯一的
就是兩個不同實例其hashcode在同一運行環境絕對不一樣 主要用來區分 兩個實例在物理上是不是同一個對象。
如:
string a ="111";
string b ="111";
a和b 的hashcode是一樣的。
其原因是java的字符串池優化原因,你聲明一個字符串時JVM會先去查找 字符串池 是否有相同字符串有將已經有的字符串對象的引用返回 而不是新生成一個字符對象到內存沒有 新生成 並將其引用放入字符串池 如此循環所以他們是同一個對象 其hashcode也一樣
至於這個
String a = newString("i love you");
String b = newString("i love you");
如果hashcode也一樣的話 那他們應該也是類似的優化。jdk5 好像不一樣吧?
hashcode()是要在容器裏面的MAP這個才能體現其價值,在MAP裏面要是重寫equals,就要重寫hashcode的方法,只要equals爲真,那麼hashcode也應該一樣。平時其他的使用hashcode沒什麼大用。
對於Object對象來說,不同的Object對象的hashcode是不同的,它們返回的是對象的地址,equals返回的也是對象的地址。
所以在自己定義的類中如果要添加到集合對象中,最好是要重寫hashcode和equals方法,不然會自動繼承自Object類中的兩個方法根據對象地址來判斷。在重寫自己定義的類時,通常是在類中的根據某個值如name.hashcode();來進行判斷。
一般來講,equals這個方法是給用戶調用的,如果你想判斷2個對象是否相等,你可以重寫equals方法,然後在代碼中調用,就可以判斷他們是否相等了。簡單來講,equals方法主要是用來判斷從表面上看或者從內容上看,2個對象是不是相等。舉個例子,有個學生類,屬性只有姓名和性別,那麼我們可以認爲只要姓名和性別相等,那麼就說這2個對象是相等的。
hashcode方法一般用戶不會去調用,比如在hashmap中,由於key是不可以重複的,他在判斷key是不是重複的時候就判斷了hashcode這個方法,而且也用到了equals方法。這裏不可以重複是說equals和hashcode只要有一個不等就可以了!所以簡單來講,hashcode相當於是一個對象的編碼,就好像文件中的md5,他和equals不同就在於他返回的是int型的,比較起來不直觀。我們一般在覆蓋equals的同時也要覆蓋hashcode,讓他們的邏輯一致。舉個例子,還是剛剛的例子,如果姓名和性別相等就算2個對象相等的話,那麼hashcode的方法也要返回姓名的hashcode值加上性別的hashcode值,這樣從邏輯上,他們就一致了。
要從物理上判斷2個對象是否相等,用==就可以了。
"=="和equals方法究竟有什麼區別?
==操作符專門用來比較兩個變量的值是否相等,也就是用於比較變量所對應的內存中所存儲的數值是否相同,要比較兩個基本類型的數據或兩個引用變量是否相等,只能用==操作符。
如果一個變量指向的數據是對象類型的,那麼,這時候涉及了兩塊內存,對象本身佔用一塊內存(堆內存),變量也佔用一塊內存,例如Objet obj = new Object();變量obj是一個內存,new Object()是另一個內存,此時,變量obj所對應的內存中存儲的數值就是對象佔用的那塊內存的首地址。對於指向對象類型的變量,如果要比較兩個變量是否指向同一個對象,即要看這兩個變量所對應的內存中的數值是否相等,這時候就需要用==操作符進行比較。
equals方法是用於比較兩個獨立對象的內容是否相同,就好比去比較兩個人的長相是否相同,它比較的兩個對象是獨立的。例如,對於下面的代碼:
String a=new String("foo");
String b=new String("foo");
兩條new語句創建了兩個對象,然後用a,b這兩個變量分別指向了其中一個對象,這是兩個不同的對象,它們的首地址是不同的,即a和b中存儲的數值是不相同的,所以,表達式a==b將返回false,而這兩個對象中的內容是相同的,所以,表達式a.equals(b)將返回true。
在實際開發中,我們經常要比較傳遞進行來的字符串內容是否等,例如,String input = …;input.equals(“quit”),許多人稍不注意就使用==進行比較了,這是錯誤的,隨便從網上找幾個項目實戰的教學視頻看看,裏面就有大量這樣的錯誤。記住,字符串的比較基本上都是使用equals方法。
如果一個類沒有自己定義equals方法,那麼它將繼承Object類的equals方法,Object類的equals方法的實現代碼如下:
boolean equals(Object o){
return this==o;
}
這說明,如果一個類沒有自己定義equals方法,它默認的equals方法(從Object類繼承的)就是使用==操作符,也是在比較兩個變量指向的對象是否是同一對象,這時候使用equals和使用==會得到同樣的結果,如果比較的是兩個獨立的對象則總返回false。如果你編寫的類希望能夠比較該類創建的兩個實例對象的內容是否相同,那麼你必須覆蓋equals方法,由你自己寫代碼來決定在什麼情況即可認爲兩個對象的內容是相同的。