一屎篱、"=="和equals方法究竟有什么區(qū)別?
-
==
操作符專門用來比較兩個(gè)變量的值是否相等
葵蒂,也就是用于比較變量所對(duì)應(yīng)的內(nèi)存中所存儲(chǔ)的數(shù)值是否相同交播,要比較兩個(gè)基本類型的數(shù)據(jù)或兩個(gè)引用變量是否相等,只能用==操作符践付。
如果一個(gè)變量指向的數(shù)據(jù)是對(duì)象類型的秦士,那么,這時(shí)候涉及了兩塊內(nèi)存永高,對(duì)象本身占用一塊內(nèi) 存(堆內(nèi)存
)隧土,變量也占用一塊內(nèi)存,例如Objet obj = new Object();變量obj是一個(gè)內(nèi)存命爬,new Object()是另一個(gè)內(nèi)存(堆內(nèi)存
),此時(shí),變量obj所對(duì)應(yīng)的內(nèi)存中存儲(chǔ)的數(shù)值就是對(duì)象占用的那塊內(nèi)存(堆內(nèi)存
)的首地址
奥裸。對(duì)于指向?qū)ο箢愋偷淖兞扛抛鳎绻容^兩個(gè)變量是否指向同一個(gè)對(duì)象,即要看這兩個(gè)變量所對(duì)應(yīng)的內(nèi)存中的數(shù)值是否相等艇抠,這時(shí)候就需要用==
操作符進(jìn)行比較幕庐。 -
equals方法是用于比較兩個(gè)獨(dú)立對(duì)象的內(nèi)容是否相同
,就好比去比較兩個(gè)人的長(zhǎng)相是否相同家淤,它比較的兩個(gè)對(duì)象是獨(dú)立的异剥。例如,對(duì)于下面的代碼:
String a=new String("foo");
String b=new String("foo");
兩條new語句創(chuàng)建了兩個(gè)對(duì)象絮重,然后用a/b這兩個(gè)變量分別指向了其中一個(gè)對(duì)象冤寿,這是兩個(gè)不同的對(duì)象错妖,它們的首地址是不同的,即a和b中存儲(chǔ)的數(shù)值(對(duì)應(yīng)對(duì)象的首地址)是不相同的
疚沐,所以暂氯,表達(dá)式a==b將返回false,而這兩個(gè)對(duì)象中的內(nèi)容是相同的亮蛔,所以痴施,表達(dá)式a.equals(b)將返回true。
如果一個(gè)類沒有自己定義equals方法(就比如之前創(chuàng)建的User類)究流,那么它將繼承Object類的equals方法辣吃,Object類的equals方法的實(shí)現(xiàn)源代碼如下:
public boolean equals(Object o) {
return this == o;
}
這說明,如果一個(gè)類沒有自己定義equals方法芬探,它默認(rèn)的equals方法(從Object類繼承的)就是使用==
操作符神得,也是在比較兩個(gè)變量指向的對(duì)象是否是同一對(duì)象,這時(shí)候使用equals和使用==會(huì)得到同樣的結(jié)果偷仿,如果比較的是兩個(gè)獨(dú)立的對(duì)象則總返回false哩簿。
二、equals()與hashcode()
hashCode()方法和equals()方法的作用其實(shí)一樣酝静,在Java里都是用來對(duì)比兩個(gè)對(duì)象是否相等一致节榜,那么equals()既然已經(jīng)能實(shí)現(xiàn)對(duì)比的功能了,為什么還要hashCode()呢别智?
因?yàn)橹貙懙膃quals()里一般比較的比較全面比較復(fù)雜宗苍,這樣效率就比較低,而利用hashCode()進(jìn)行對(duì)比薄榛,則只要生成一個(gè)hash值進(jìn)行比較就可以了讳窟,效率很高,那么hashCode()既然效率這么高為什么還要equals()呢敞恋?
因?yàn)閔ashCode()并不是完全可靠丽啡,有時(shí)候不同的對(duì)象他們生成的hashcode也會(huì)一樣(hash沖突),所以hashCode()只能說是大部分時(shí)候可靠耳舅,并不是絕對(duì)可靠碌上,所以可以得出:
- equals()相等的兩個(gè)對(duì)象他們的hashCode()肯定相等,也就是用equals()對(duì)比是絕對(duì)可靠的浦徊。
- hashCode()相等的兩個(gè)對(duì)象他們的equals()不一定相等馏予,也就是hashCode()不是絕對(duì)可靠的。
那是不是重寫了equals()方法就一定要重寫hashCode()方法呢盔性?
一般來說涉及到對(duì)象之間的比較大小就需要重寫equals方法霞丧,但是不是重寫了equals就需要重寫hashCode呢?實(shí)際上這只是一條規(guī)范冕香,如果不這樣做程序也可以執(zhí)行蛹尝,只不過會(huì)存在潛在bug后豫。一般一個(gè)類的對(duì)象如果會(huì)存儲(chǔ)在HashTable,HashSet,HashMap等散列存儲(chǔ)結(jié)構(gòu)中,那么重寫equals后最好也重寫hashCode突那,否則會(huì)導(dǎo)致存儲(chǔ)數(shù)據(jù)的不唯一性(存儲(chǔ)了兩個(gè)equals相等的數(shù)據(jù))挫酿。而如果確定不會(huì)存儲(chǔ)在這些散列結(jié)構(gòu)中,則可以不重寫hashCode愕难。但是個(gè)人覺得還是重寫hashCode比較好一點(diǎn)早龟,這樣就不用考慮后期存儲(chǔ)在哪些結(jié)構(gòu)中,況且重寫了hashCode也不會(huì)降低性能猫缭,因?yàn)樵诰€性結(jié)構(gòu)(如ArrayList)中是不會(huì)調(diào)用hashCode葱弟。
下面看一下一個(gè)對(duì)象放入散列集合的大致流程:
- 準(zhǔn)備即將放入集合的對(duì)象
- 判斷集合中是否存在hashCode值與這個(gè)對(duì)象相等的對(duì)象
- 存在hashCode值相等的對(duì)象
判斷該對(duì)象和要放入對(duì)象的equals是否相等- 相等 --> 直接丟棄
- 不相等 --> 存入集合
- 不存在hashCode值相等的集合
直接存入集合
- 存在hashCode值相等的對(duì)象
所有對(duì)于需要大量并且快速的對(duì)比的話如果都用equals()去做顯然效率太低,所以解決方式是猜丹,每當(dāng)需要對(duì)比的時(shí)候芝加,首先用hashCode()去對(duì)比,如果hashCode()不一樣射窒,則表示這兩個(gè)對(duì)象肯定不相等(也就是不必再用equals()去再對(duì)比了),如果hashCode()相同藏杖,此時(shí)再對(duì)比他們的equals(),如果equals()也相同轮洋,則表示這兩個(gè)對(duì)象是真的相同了制市,這樣既能大大提高了效率也保證了對(duì)比的絕對(duì)正確性!