==
【進(jìn)行等值比較】
java中的數(shù)據(jù)類型分為:
- 基本數(shù)據(jù)類型(原始數(shù)據(jù)類型)
(byte,short,char,int,long,float,double,boolean)
這些數(shù)據(jù)的值直接存儲(chǔ)在Java棧中拢锹,他們之間的比較應(yīng)使用雙等號(hào)(==)谣妻。 - 引用類型(類、接口卒稳、數(shù)組)
使用(==)對此類數(shù)據(jù)進(jìn)行比較時(shí)比較的是實(shí)際的數(shù)據(jù)在內(nèi)存中的存放地址蹋半。因此,只有當(dāng)兩個(gè)變量引用的是同一個(gè)對象時(shí)充坑,使用(==)比較時(shí)結(jié)果才為true减江,否則結(jié)果為false染突。
對象本身是放在堆中的,棧中存放的是對象的引用(地址)辈灼。
由此可見'=='是對棧中的值進(jìn)行比較的份企。
如果要比較堆中對象的內(nèi)容是否相同,那么就要重寫equals方法茵休。
equals()
①默認(rèn)情況下薪棒,若沒有重寫equals方法手蝎,調(diào)用equals方法時(shí)都是調(diào)用Object類的equals方法榕莺,而Object的equals方法主要用于判斷對象的內(nèi)存地址引用是不是同一個(gè)地址(是不是同一個(gè)對象)。下面是Object類中equals方法:
public boolean equals(Object obj) {
return (this == obj);
}
此時(shí)棵介,equals()和==時(shí)等效的钉鸯。
②若類中覆蓋了equals方法,那么需要根據(jù)具體的代碼來確定equals方法的作用
例如邮辽,String類重寫了equals()方法:
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = count;
if (n == anotherString.count) {
char v1[] = value;
char v2[] = anotherString.value;
int i = offset;
int j = anotherString.offset;
while (n-- != 0) {
if (v1[i++] != v2[j++])
return false;
}
return true;
}
}
return false;
}
String中equals方法判斷相等的步驟是:
若A==B 即是同一個(gè)String對象 返回true
若對比對象是String類型則繼續(xù)唠雕,否則返回false
判斷A、B長度是否一樣吨述,不一樣的話返回false
逐個(gè)字符比較岩睁,若有不相等字符,返回false
重寫equals的注意點(diǎn):
- 自反性:對任意引用值X揣云,x.equals(x)的返回值一定為true.
- 對稱性:對于任何引用值x,y,當(dāng)且僅當(dāng)y.equals(x)返回值為true時(shí)捕儒,x.equals(y)的返回值一定為true;
- 傳遞性:如果x.equals(y)=true, y.equals(z)=true,則x.equals(z)=true
- 一致性:如果參與比較的對象沒任何改變,則對象比較的結(jié)果也不應(yīng)該有任何改變
- 非空性:任何非空的引用值X邓夕,x.equals(null)的返回值一定為false
重寫euqals的一般步驟:
- 使用==符號(hào)檢查“參數(shù)是否為這個(gè)對象的引用”刘莹。如果是,則返回true焚刚。這只不過是一種性能優(yōu)化点弯,如果比較操作有可能很昂貴,就值得這么做矿咕。
- 使用instanceof操作符檢查“參數(shù)是否為正確的類型”抢肛。如果不是,則返回false碳柱。一般來說雌团,所謂“正確的類型”是指equals方法所在的那個(gè)類。
- 把參數(shù)轉(zhuǎn)換成正確的類型士聪。因?yàn)檗D(zhuǎn)換之前進(jìn)行過instanceof測試锦援,所以確保會(huì)成功。
- 對于該類中的每個(gè)“關(guān)鍵”域剥悟,檢查參數(shù)中的域是否與該對象中對應(yīng)的域相匹配灵寺。如果這些測試全部成功曼库,則返回true;否則返回false。
- 當(dāng)編寫完成了equals方法之后略板,檢查“對稱性”毁枯、“傳遞性”、“一致性”叮称。
hashCode()
hashCode() 的作用是獲取哈希碼种玛,也稱為散列碼;它實(shí)際上是返回一個(gè)int整數(shù)瓤檐。hash碼的主要用途就是確定該對象在哈希表中的索引位置赂韵,據(jù)此很容易推斷出,我們需要每個(gè)對象的hash碼盡可能不同挠蛉,這樣才能保證散列的存取性能祭示。
事實(shí)上,Object類提供的默認(rèn)實(shí)現(xiàn)確實(shí)保證每個(gè)對象的hash碼不同(在對象的內(nèi)存地址基礎(chǔ)上經(jīng)過特定算法返回一個(gè)hash碼)谴古。Java采用了哈希表的原理质涛。哈希(Hash)實(shí)際上是個(gè)人名,由于他提出一哈希算法的概念掰担,所以就以他的名字命名了汇陆。
hashCode() 定義在JDK的Object.java中,這就意味著Java中的任何類都包含有hashCode() 函數(shù)带饱。
簡單來說毡代,hashCode()方法是一種從任何一種數(shù)據(jù)中創(chuàng)建小的數(shù)字“指紋”的方法。 散列函數(shù)將任意長度的二進(jìn)制值映射為較短的固定長度的二進(jìn)制值纠炮,這個(gè)小的二進(jìn)制值稱為哈希值月趟。
hashCode()和equals()的聯(lián)系
- 同一對象上多次調(diào)用hashCode()方法,總是返回相同的整型值恢口。
- 如果兩個(gè)對象equals孝宗,Java運(yùn)行時(shí)環(huán)境會(huì)認(rèn)為他們的hashcode一定相等。
- 如果兩個(gè)對象不equals耕肩,他們的hashcode有可能相等因妇。
- 如果兩個(gè)對象hashcode相等,他們不一定equals猿诸。
- 如果兩個(gè)對象hashcode不相等婚被,他們一定不equals。
重寫兩個(gè)方法時(shí)應(yīng)尊重的規(guī)范:
- 若重寫equals(Object obj)方法梳虽,有必要重寫hashcode()方法址芯,確保通過equals(Object obj)方法判斷結(jié)果為true的兩個(gè)對象具備相等的hashcode()返回值。
- 如果equals(Object obj)返回false,即兩個(gè)對象“不相同”谷炸,并不要求兩個(gè)對象的hashcode()方法返回兩個(gè)相同的值北专。
總結(jié)
- equals方法用于比較對象的內(nèi)容是否相等(覆蓋以后)
- hashcode方法只有在集合中用到
- 當(dāng)覆蓋了equals方法時(shí),比較對象是否相等將通過覆蓋后的equals方法進(jìn)行比較(判斷對象的內(nèi)容是否相等)旬陡。
- 將對象放入到集合中時(shí)拓颓,首先判斷要放入對象的hashcode值與集合中的任意一個(gè)元素的hashcode值是否相等,如果不相等直接將該對象放入集合中描孟。
(如果hashcode值相等驶睦,然后再通過equals方法判斷要放入對象與集合中的任意一個(gè)對象是否相等,如果equals判斷不相等匿醒,直接將該元素放入到集合中场航,否則不放入。)
歡迎到作者github主頁交流