java中equals群嗤,hashcode和==的區(qū)別

1、==

java中的數(shù)據(jù)類型兵琳,可分為兩類:

1.基本數(shù)據(jù)類型狂秘,也稱原始數(shù)據(jù)類型

byte,short,char,int,long,float,double,boolean 他們之間的比較骇径,應用雙等號(==),比較的是他們的值。

2.引用類型(類者春、接口破衔、數(shù)組)

當他們用(==)進行比較的時候,比較的是他們在內存中的存放地址钱烟,所以晰筛,除非是同一個new出來的對象,他們的比較后的結果為true拴袭,否則比較后結果為false读第。

對象是放在堆中的,棧中存放的是對象的引用(地址)拥刻。由此可見'=='是對棧中的值進行比較的怜瞒。如果要比較堆中對象的內容是否相同,那么就要重寫equals方法了般哼。

例:

public static void main(String[] args) {  

    int int1 = 12;  
    int int2 = 12;  
    Integer Integer1 = new Integer(12);  
    Integer Integer2 = new Integer(12);  
    Integer Integer3 = new Integer(127);  

    Integer a1 = 127;  
    Integer b1 = 127;  

    Integer a = 128;  
    Integer b = 128;  

    String s1 = "str";  
    String s2 = "str";  
    String str1 = new String("str");  
    String str2 = new String("str");  

    System.out.println("int1==int2:" + (int1 == int2));  
    System.out.println("int1==Integer1:" + (int1 == Integer1));  
    System.out.println("Integer1==Integer2:" + (Integer1 == Integer2));  
    System.out.println("Integer3==b1:" + (Integer3 == b1));  
    System.out.println("a1==b1:" + (a1 == b1));  
    System.out.println("a==b:" + (a == b));  
      

    System.out.println("s1==s2:" + (s1 == s2));  
    System.out.println("s1==str1:" + (s1 == str1));  
    System.out.println("str1==str2:" + (str1 == str2));  

} 

輸出結果:

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);

public static Integer valueOf(int i) {  
     assert IntegerCache.high >= 127;  
     if (i >= IntegerCache.low && i <= IntegerCache.high)  
         return IntegerCache.cache[i + (-IntegerCache.low)];  
     return new Integer(i);  
 }  

看一下源碼大家都會明白,對于-128到127之間的數(shù)擒贸,會進行緩存臀晃,Integer b1 = 127時,會將127進行緩存介劫,下次再寫Integer i6 = 127時徽惋,就會直接從緩存中取,就不會new了座韵。所以a1==b1:true a==b:false

2险绘、equals

1、默認情況(沒有覆蓋equals方法)下equals方法都是調用Object類的equals方法誉碴,而Object的equals方法主要用于判斷對象的內存地址引用是不是同一個地址(是不是同一個對象)宦棺。下面是Object類中equals方法:

public boolean equals(Object obj) {  
       return (this == obj);  
}  

定義的equals與==是等效的

2 、要是類中覆蓋了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方法判斷相等的步驟是:

1.若A==B 即是同一個String對象 返回true

2.若對比對象是String類型則繼續(xù)成黄,否則返回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

實現(xiàn)高質量equals方法的訣竅:
1.使用==符號檢查“參數(shù)是否為這個對象的引用”铡买。如果是更鲁,則返回true。這只不過是一種性能優(yōu)化奇钞,如果比較操作有可能很昂貴澡为,就值得這么做。
2.使用instanceof操作符檢查“參數(shù)是否為正確的類型”景埃。如果不是媒至,則返回false。一般來說谷徙,所謂“正確的類型”是指equals方法所在的那個類拒啰。
3.把參數(shù)轉換成正確的類型。因為轉換之前進行過instanceof測試完慧,所以確保會成功谋旦。
4.對于該類中的每個“關鍵”域,檢查參數(shù)中的域是否與該對象中對應的域相匹配屈尼。如果這些測試全部成功册着,則返回true;否則返回false。
5.當編寫完成了equals方法之后脾歧,檢查“對稱性”甲捏、“傳遞性”、“一致性”鞭执。

3司顿、hashCode

hashCode()方法返回的就是一個數(shù)值,從方法的名稱上就可以看出兄纺,其目的是生成一個hash碼免猾。hash碼的主要用途就是在對對象進行散列的時候作為key輸入,據(jù)此很容易推斷出囤热,我們需要每個對象的hash碼盡可能不同猎提,這樣才能保證散列的存取性能。事實上,Object類提供的默認實現(xiàn)確實保證每個對象的hash碼不同(在對象的內存地址基礎上經過特定算法返回一個hash碼)锨苏。Java采用了哈希表的原理疙教。哈希(Hash)實際上是個人名,由于他提出一哈希算法的概念伞租,所以就以他的名字命名了贞谓。 哈希算法也稱為散列算法,是將數(shù)據(jù)依特定算法直接指定到一個地址上葵诈。初學者可以這樣理解裸弦,hashCode方法實際上返回的就是對象存儲的物理地址(實際可能并不是)。

散列函數(shù),散列算法,哈希函數(shù)作喘。
是一種從任何一種數(shù)據(jù)中創(chuàng)建小的數(shù)字“指紋”的方法理疙。
散列函數(shù)將任意長度的二進制值映射為較短的固定長度的二進制值,這個小的二進制值稱為哈希值泞坦。
好的散列函數(shù)在輸入域中很少出現(xiàn)散列沖突窖贤。
=================================================================================
所有散列函數(shù)都有如下一個基本特性:
1:如果a=b,則h(a) = h(b)贰锁。
2:如果a!=b赃梧,則h(a)與h(b)可能得到相同的散列值。

Object 的hashCode方法:返回一個int類型

public native int hashCode(); 

3.1 hashCode的作用

想要明白豌熄,必須要先知道Java中的集合授嘀。  
總的來說锣险,Java中的集合(Collection)有兩類蹄皱,一類是List,再有一類是Set囱持。前者集合內的元素是有序的夯接,元素可以重復焕济;后者元素無序纷妆,但元素不可重復。

那么這里就有一個比較嚴重的問題了:要想保證元素不重復晴弃,可兩個元素是否重復應該依據(jù)什么來判斷呢掩幢?

這就是Object.equals方法了。但是上鞠,如果每增加一個元素就檢查一次际邻,那么當元素很多時,后添加到集合中的元素比較的次數(shù)就非常多了芍阎。也就是說世曾,如果集合中現(xiàn)在已經有1000個元素,那么第1001個元素加入集合時谴咸,它就要調用1000次equals方法轮听。這顯然會大大降低效率骗露。
于是,Java采用了哈希表的原理血巍。

這樣一來萧锉,當集合要添加新的元素時,

先調用這個元素的hashCode方法述寡,就一下子能定位到它應該放置的物理位置上柿隙。

如果這個位置上沒有元素歼争,它就可以直接存儲在這個位置上傍菇,不用再進行任何比較了命爬;

如果這個位置上已經有元素了照捡,就調用它的equals方法與新元素進行比較出刷,相同的話就不存八回,不相同就散列其它的地址帖旨。所以這里存在一個沖突解決的問題找田。這樣一來實際調用equals方法的次數(shù)就大大降低了不恭,幾乎只需要一兩次叶雹。

4、eqauls方法和hashCode方法關系

Java對于eqauls方法和hashCode方法是這樣規(guī)定的:

(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)為假缕探。

上面結論簡記:

1魂莫、如果兩個對象equals,Java運行時環(huán)境會認為他們的hashcode一定相等爹耗。
2耙考、如果兩個對象不equals,他們的hashcode有可能相等潭兽。
3倦始、如果兩個對象hashcode相等,他們不一定equals山卦。
4鞋邑、如果兩個對象hashcode不相等,他們一定不equals。

關于這兩個方法的重要規(guī)范:

規(guī)范1:若重寫equals(Object obj)方法枚碗,有必要重寫hashcode()方法藻懒,確保通過equals(Object obj)方法判斷結果為true的兩個對象具備相等的hashcode()返回值。說得簡單點就是:“如果兩個對象相同视译,那么他們的hashcode應該相等”嬉荆。不過請注意:這個只是規(guī)范,如果你非要寫一個類讓equals(Object obj)返回true而hashcode()返回兩個不相等的值酷含,編譯和運行都是不會報錯的鄙早。不過這樣違反了Java規(guī)范,程序也就埋下了BUG椅亚。

規(guī)范2:如果equals(Object obj)返回false限番,即兩個對象“不相同”,并不要求對這兩個對象調用hashcode()方法得到兩個不相同的數(shù)呀舔。說的簡單點就是:“如果兩個對象不相同弥虐,他們的hashcode可能相同”。

5媚赖、為什么覆蓋equals時總要覆蓋hashCode

一個很常見的錯誤根源在于沒有覆蓋hashCode方法霜瘪。在每個覆蓋了equals方法的類中,也必須覆蓋hashCode方法惧磺。如果不這樣做的話颖对,就會違反Object.hashCode的通用約定,從而導致該類無法結合所有基于散列的集合一起正常運作磨隘,這樣的集合包括HashMap缤底、HashSet和Hashtable。

1.在應用程序的執(zhí)行期間番捂,只要對象的equals方法的比較操作所用到的信息沒有被修改个唧,那么對這同一個對象調用多次,hashCode方法都必須始終如一地返回同一個整數(shù)设预。在同一個應用程序的多次執(zhí)行過程中徙歼,每次執(zhí)行所返回的整數(shù)可以不一致。

2.如果兩個對象根據(jù)equals()方法比較是相等的絮缅,那么調用這兩個對象中任意一個對象的hashCode方法都必須產生同樣的整數(shù)結果鲁沥。

3.如果兩個對象根據(jù)equals()方法比較是不相等的呼股,那么調用這兩個對象中任意一個對象的hashCode方法耕魄,則不一定要產生相同的整數(shù)結果。但是程序員應該知道彭谁,給不相等的對象產生截然不同的整數(shù)結果吸奴,有可能提高散列表的性能。

6、總結:

1则奥、equals方法用于比較對象的內容是否相等(覆蓋以后)

2考润、hashcode方法只有在集合中用到

3、當覆蓋了equals方法時读处,比較對象是否相等將通過覆蓋后的equals方法進行比較(判斷對象的內容是否相等)糊治。

4、將對象放入到集合中時罚舱,首先判斷要放入對象的hashcode值與集合中的任意一個元素的hashcode值是否相等井辜,如果不相等直接將該對象放入集合中。如果hashcode值相等管闷,然后再通過equals方法判斷要放入對象與集合中的任意一個對象是否相等粥脚,如果equals判斷不相等,直接將該元素放入到集合中包个,否則不放入刷允。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市碧囊,隨后出現(xiàn)的幾起案子树灶,更是在濱河造成了極大的恐慌,老刑警劉巖糯而,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件破托,死亡現(xiàn)場離奇詭異,居然都是意外死亡歧蒋,警方通過查閱死者的電腦和手機土砂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來谜洽,“玉大人萝映,你說我怎么就攤上這事〔椋” “怎么了序臂?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長实束。 經常有香客問我奥秆,道長,這世上最難降的妖魔是什么咸灿? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任构订,我火速辦了婚禮,結果婚禮上避矢,老公的妹妹穿的比我還像新娘悼瘾。我一直安慰自己囊榜,他們只是感情好,可當我...
    茶點故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布亥宿。 她就那樣靜靜地躺著卸勺,像睡著了一般。 火紅的嫁衣襯著肌膚如雪烫扼。 梳的紋絲不亂的頭發(fā)上曙求,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天,我揣著相機與錄音映企,去河邊找鬼圆到。 笑死,一個胖子當著我的面吹牛卑吭,可吹牛的內容都是我干的芽淡。 我是一名探鬼主播,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼豆赏,長吁一口氣:“原來是場噩夢啊……” “哼挣菲!你這毒婦竟也來了?” 一聲冷哼從身側響起掷邦,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤白胀,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后抚岗,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體或杠,經...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年宣蔚,在試婚紗的時候發(fā)現(xiàn)自己被綠了向抢。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,064評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡胚委,死狀恐怖挟鸠,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情亩冬,我是刑警寧澤艘希,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站硅急,受9級特大地震影響覆享,放射性物質發(fā)生泄漏。R本人自食惡果不足惜营袜,卻給世界環(huán)境...
    茶點故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一撒顿、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧连茧,春花似錦核蘸、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至罚斗,卻和暖如春徙鱼,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背针姿。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工袱吆, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人距淫。 一個月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓绞绒,卻偏偏與公主長得像,于是被迫代替她去往敵國和親榕暇。 傳聞我的和親對象是個殘疾皇子蓬衡,可洞房花燭夜當晚...
    茶點故事閱讀 42,802評論 2 345

推薦閱讀更多精彩內容