一、==html
java中的數據類型,可分爲兩類:java
1.基本數據類型,也稱原始數據類型程序員
byte,short,char,int,long,float,double,boolean 他們之間的比較,應用雙等號(==),比較的是他們的值。 算法
2.引用類型(類、接口、數組) 數組
當他們用(==)進行比較的時候,比較的是他們在內存中的存放地址,因此,除非是同一個new出來的對象,他們的比較後的結果爲true,不然比較後結果爲false。緩存
對象是放在堆中的,棧中存放的是對象的引用(地址)。因而可知'=='是對棧中的值進行比較的。若是要比較堆中對象的內容是否相同,那麼就要重寫equals方法了。 性能優化
例:app
[java] view plain copy函數
輸出結果:性能
int1==int2:true
int1==Integer1:true //Integer會自動拆箱爲int,因此爲true
Integer1==Integer2:false//不一樣對象,在內存存放地址不一樣,因此爲false
Integer3==b1:false//Integer3指向new的對象地址,b1指向緩存中127地址,地址不一樣,因此爲false
a1==b1:true
a==b:false
s1==s2:true
s1==str1:false
str1==str2:false
Integer b1 = 127;java在編譯的時候,被翻譯成-> Integer b1 = Integer.valueOf(127);
[java] view plain copy
看一下源碼你們都會明白,對於-128到127之間的數,會進行緩存,Integer b1 = 127時,會將127進行緩存,下次再寫Integer i6 = 127時,就會直接從緩存中取,就不會new了。因此a1==b1:true a==b:false
二、equals
一、默認狀況(沒有覆蓋equals方法)下equals方法都是調用Object類的equals方法,而Object的equals方法主要用於判斷對象的內存地址引用是否是同一個地址(是否是同一個對象)。下面是Object類中equals方法:
[java] view plain copy
定義的equals與==是等效的
2 、要是類中覆蓋了equals方法,那麼就要根據具體的代碼來肯定equals方法的做用了,覆蓋後通常都是經過對象的內容是否相等來判斷對象是否相等。下面是String類對equals進行了重寫:
[java] view plain copy
即String中equals方法判斷相等的步驟是:
1.若A==B 便是同一個String對象 返回true
2.若對比對象是String類型則繼續,不然返回false
3.判斷A、B長度是否同樣,不同的話返回false
4。逐個字符比較,如有不相等字符,返回false
這裏對equals從新須要注意五點:
1 自反性:對任意引用值X,x.equals(x)的返回值必定爲true.
2 對稱性:對於任何引用值x,y,當且僅當y.equals(x)返回值爲true時,x.equals(y)的返回值必定爲true;
3 傳遞性:若是x.equals(y)=true, y.equals(z)=true,則x.equals(z)=true
4 一致性:若是參與比較的對象沒任何改變,則對象比較的結果也不該該有任何改變
5 非空性:任何非空的引用值X,x.equals(null)的返回值必定爲false
實現高質量equals方法的訣竅:
1.使用==符號檢查「參數是否爲這個對象的引用」。若是是,則返回true。這只不過是一種性能優化,若是比較操做有可能很昂貴,就值得這麼作。
2.使用instanceof操做符檢查「參數是否爲正確的類型」。若是不是,則返回false。通常來講,所謂「正確的類型」是指equals方法所在的那個類。
3.把參數轉換成正確的類型。由於轉換以前進行過instanceof測試,因此確保會成功。
4.對於該類中的每一個「關鍵」域,檢查參數中的域是否與該對象中對應的域相匹配。若是這些測試所有成功,則返回true;不然返回false。
5.當編寫完成了equals方法以後,檢查「對稱性」、「傳遞性」、「一致性」。
三、hashCode
hashCode()方法返回的就是一個數值,從方法的名稱上就能夠看出,其目的是生成一個hash碼。hash碼的主要用途就是在對對象進行散列的時候做爲key輸入,據此很容易推斷出,咱們須要每一個對象的hash碼儘量不一樣,這樣才能保證散列的存取性能。事實上,Object類提供的默認實現確實保證每一個對象的hash碼不一樣(在對象的內存地址基礎上通過特定算法返回一個hash碼)。Java採用了哈希表的原理。哈希(Hash)其實是我的名,因爲他提出一哈希算法的概念,因此就以他的名字命名了。 哈希算法也稱爲散列算法,是將數據依特定算法直接指定到一個地址上。初學者能夠這樣理解,hashCode方法實際上返回的就是對象存儲的物理地址(實際可能並非)。
散列函數,散列算法,哈希函數。
是一種從任何一種數據中建立小的數字「指紋」的方法。
散列函數將任意長度的二進制值映射爲較短的固定長度的二進制值,這個小的二進制值稱爲哈希值。
好的散列函數在輸入域中不多出現散列衝突。
=================================================================================
全部散列函數都有以下一個基本特性:
1:若是a=b,則h(a) = h(b)。
2:若是a!=b,則h(a)與h(b)可能獲得相同的散列值。
Object 的hashCode方法:返回一個int類型
[java] view plain copy
3.1 hashCode的做用
想要明白,必需要先知道Java中的集合。
總的來講,Java中的集合(Collection)有兩類,一類是List,再有一類是Set。前者集合內的元素是有序的,元素能夠重複;後者元素無序,但元素不可重複。
那麼這裏就有一個比較嚴重的問題了:要想保證元素不重複,可兩個元素是否重複應該依據什麼來判斷呢?
這就是Object.equals方法了。可是,若是每增長一個元素就檢查一次,那麼當元素不少時,後添加到集合中的元素比較的次數就很是多了。也就是說,若是集合中如今已經有1000個元素,那麼第1001個元素加入集合時,它就要調用1000次equals方法。這顯然會大大下降效率。
因而,Java採用了哈希表的原理。
這樣一來,當集合要添加新的元素時,
先調用這個元素的hashCode方法,就一會兒能定位到它應該放置的物理位置上。
若是這個位置上沒有元素,它就能夠直接存儲在這個位置上,不用再進行任何比較了;
若是這個位置上已經有元素了,就調用它的equals方法與新元素進行比較,相同的話就不存,不相同就散列其它的地址。因此這裏存在一個衝突解決的問題。這樣一來實際調用equals方法的次數就大大下降了,幾乎只須要一兩次。
四、eqauls方法和hashCode方法關係
Java對於eqauls方法和hashCode方法是這樣規定的:
(1)同一對象上屢次調用hashCode()方法,老是返回相同的整型值。
(2)若是a.equals(b),則必定有a.hashCode() 必定等於 b.hashCode()。
(3)若是!a.equals(b),則a.hashCode() 不必定等於 b.hashCode()。此時若是a.hashCode() 老是不等於 b.hashCode(),會提升hashtables的性能。
(4)a.hashCode()==b.hashCode() 則 a.equals(b)可真可假
(5)a.hashCode()!= b.hashCode() 則 a.equals(b)爲假。
上面結論簡記:
一、若是兩個對象equals,Java運行時環境會認爲他們的hashcode必定相等。
二、若是兩個對象不equals,他們的hashcode有可能相等。
三、若是兩個對象hashcode相等,他們不必定equals。
四、若是兩個對象hashcode不相等,他們必定不equals。
關於這兩個方法的重要規範:
規範1:若重寫equals(Object obj)方法,有必要重寫hashcode()方法,確保經過equals(Object obj)方法判斷結果爲true的兩個對象具有相等的hashcode()返回值。說得簡單點就是:「若是兩個對象相同,那麼他們的hashcode應該相等」。不過請注意:這個只是規範,若是你非要寫一個類讓equals(Object obj)返回true而hashcode()返回兩個不相等的值,編譯和運行都是不會報錯的。不過這樣違反了Java規範,程序也就埋下了BUG。
規範2:若是equals(Object obj)返回false,即兩個對象「不相同」,並不要求對這兩個對象調用hashcode()方法獲得兩個不相同的數。說的簡單點就是:「若是兩個對象不相同,他們的hashcode可能相同」。
五、爲何覆蓋equals時總要覆蓋hashCode
一個很常見的錯誤根源在於沒有覆蓋hashCode方法。在每一個覆蓋了equals方法的類中,也必須覆蓋hashCode方法。若是不這樣作的話,就會違反Object.hashCode的通用約定,從而致使該類沒法結合全部基於散列的集合一塊兒正常運做,這樣的集合包括HashMap、HashSet和Hashtable。
1.在應用程序的執行期間,只要對象的equals方法的比較操做所用到的信息沒有被修改,那麼對這同一個對象調用屢次,hashCode方法都必須始終如一地返回同一個整數。在同一個應用程序的屢次執行過程當中,每次執行所返回的整數能夠不一致。
2.若是兩個對象根據equals()方法比較是相等的,那麼調用這兩個對象中任意一個對象的hashCode方法都必須產生一樣的整數結果。
3.若是兩個對象根據equals()方法比較是不相等的,那麼調用這兩個對象中任意一個對象的hashCode方法,則不必定要產生相同的整數結果。可是程序員應該知道,給不相等的對象產生大相徑庭的整數結果,有可能提升散列表的性能。
六、總結:
一、equals方法用於比較對象的內容是否相等(覆蓋之後)
二、hashcode方法只有在集合中用到
三、當覆蓋了equals方法時,比較對象是否相等將經過覆蓋後的equals方法進行比較(判斷對象的內容是否相等)。
四、將對象放入到集合中時,首先判斷要放入對象的hashcode值與集合中的任意一個元素的hashcode值是否相等,若是不相等直接將該對象放入集合中。若是hashcode值相等,而後再經過equals方法判斷要放入對象與集合中的任意一個對象是否相等,若是equals判斷不相等,直接將該元素放入到集合中,不然不放入。
參考來源: