摘要:而這次在一的一方實體里重寫基類的和方法做去重,感覺用的代碼量減少了,又能提高效率,所以我這里對這兩個方法做些自己的理解。不相等的兩個對象,不一定不相等。不相等,那么是一定不等的。文章若有錯誤之處,歡迎指出。
昨天寫hibernate一對多查詢的時候,用set集合來儲存值,
我們都知道java中List集合是有序,可重復的,Set集合是無序,不可重復的。所以當時寫這個查詢的時候果斷用Set來存值,但還是出現了值重復問題。
具體請看SF上提問:https://segmentfault.com/q/10...
我之前做的在for里對set有去重做法,但是有不足之處的。而這次在“一”的一方實體里重寫Object基類的hashCode和equals方法做去重,感覺用的代碼量減少了,又能提高效率,所以我這里對這兩個方法做些自己的理解。
1、hashCode()和equals()是什么
hashCode和equals方法是在Object基類中,所以每個對象都可以重寫這兩個方法,
看看JDK中這兩個方法源碼
hashCode
/** * 查看hashCode源碼是native修飾的, 說明這個方法是個原生函數, * 也就是說這個方法不是用java實現的,底層是用C/C++實現的 * 返回哈希值 */ public native int hashCode();
equals
/* 用來比較兩個引用所指向的對象內存地址是否一致 */ public boolean equals(Object obj) { return (this == obj); }
2、hashCode()和equals()關系是什么?
明白幾個原則:
equals相等的兩個對象,hashcode一定相等。
equals不相等的兩個對象,hashcode不一定不相等。
hashcode不相等,那么equals是一定不等的。
hashcode相等,equals可能相等,也可能不等。
解釋下第四個原則:
就好比hashcode像是一個詞典目錄里的按字母為索引查找字,查一個“Z”拼音開頭的詞,下面等查到“自己”,“自我”,“知道”等詞,用equals就是判斷這些詞語當中是否有相等的詞,“自己”和“知道”兩個詞不相等的,所以equals值不等,但它們同屬于"Z"開頭的詞所以它們hashcode值相等。
3、為什么重寫equals的同時也要重寫hashCode呢?
這個問題不難解釋,就像前面問題一樣,hash算法是為了提高equals比較的效率而被發明出來的。這點在集合方面就能體現出來,就比如在List或Set集合里要比較是否有重復元素,當發現某個集合對象與另一個集合對象equals比較的結果相等時,則停止查找返回true值,反之,返回false值。但如果集合中有大量元素呢,假設一個集合A里有10萬元素,而且另一個比較的對象B中還可能沒有重復的值,則意味著其實不用比較我都知道兩者不相同,但程序依然會對集合A里遍歷10萬元素然后和B進行逐一排查。。。又或者當我要加入第100001個數據我要驗證前面元素有重復值,就要跟前面10萬個元素一一比較,效率可想而知很低。
而哈希算法就是Java系統首先調用對象的hashCode()方法獲得該對象的哈希碼表,然后根據哈希碼找到相應的存儲區域,若哈希碼相同在取得該存儲區域內的每個元素與該對象進行equals方法比較,若不同也就沒有繼續比較的必要了,這對于數量較大的情況效率就提高了不少,重寫hashcode方法,最主要就是保證操作的元素在同一個對象里且值都沒有重復,若沒有重寫hashcode,可能會出現將對象引用不同,但元素完全相同的集合進行操作。
下面寫一個例子
package demo; public class override_HshCode_Equals { public int x; public int y; public override_HshCode_Equals(int x, int y) { this.x = x; this.y = y; } @Override public int hashCode() { //下面變量初始化值可以任意取 final int prime = 31; int result = 1; result = prime * result + x; result = prime * result + y; return result; } /** * equals返回false就說明沒有重復項可以添加 * true是重復不能添加 */ @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; final override_HshCode_Equals heClass = (override_HshCode_Equals) obj; //這里就對實例化對象里的x,y進行比較 if (x != heClass.x) { return false; } if (y != heClass.y) { return false; } return true; } }
測試類
package demo; import java.util.HashSet; public class TestMain { public static void main(String[] args) { HashSetset = new HashSet (); override_HshCode_Equals heClass1 = new override_HshCode_Equals(1, 1); override_HshCode_Equals heClass2 = new override_HshCode_Equals(5, 5); override_HshCode_Equals heClass3 = new override_HshCode_Equals(1, 1); set.add(heClass1); set.add(heClass2); set.add(heClass3); set.add(heClass1); System.out.println("set數量=" + set.size()); } }
結果如下
set數量=2
注:重寫override_HshCode_Equals類的hashCode相當于自定義返回了一個“哈希碼”,對比x,y值是否相等,先比較hashcode值,heClass1(3,3)==heClass3(3,3),所以它們的hashcode值相等,但是heClass2的x,y和heClass1,heClass3的x,y值不等,所以hashcode不等,equals一定不等,所以heClass2對象是可以add進去的。前面說了heClass1和heClass3的hashcode值相等,然后進入equals進行對比,發現兩者的對象都是相同的,根據程序add循序來看,所以heClass1是可以add進去的,然后heClass3和后面add(heClass1)都為重復項,就不會添加
注釋override_HshCode_Equals里的hashCode方法
結果如下
set數量=3
注:首先判斷heClass1對象和heClass2對象的hashCode,此時Object中的hashCode方法返回的是對象本地內存地址的換算結果,不同的實例對象的hashCode是不相同的,同樣因為heClass3和heClass1的hashCode也是不相等的,但是后面第四個添加中heClass1==heClass1的,所以最后set集合中只有heClass1,heClass2,heClass3這三個對象。
修改:override_HshCode_Equals heClass3 = new override_HshCode_Equals(1, 2);
結果如下
set數量=3
注:此時對比heClass1,heClass2,heClass3的x,y值都不相同,hashcode值不同,而第四個添加heClass1=heClass1,故添加不進去,set里有heClass1,heClass2,heClass3。
文章若有錯誤之處,歡迎指出。
參考網站: http://www.cnblogs.com/ysch/p/4323889.html
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/70440.html
摘要:的工作原理是近年來常見的面試題。讓我們再來看看這些問題設計哪些知識點的概念中解決碰撞的方法和的應用,以及它們在中的重要性不可變對象的好處多線程的條件競爭重新調整的大小總結的工作原理基于原理,我們通過和方法儲存和獲取對象。 HashMap 的工作原理是近年來常見的 Java 面試題。幾乎每個 Java 程序員都知道 HashMap,都知道哪里要用 HashMap,知道Hashtable和...
摘要:根據的重新計算值。如果這兩個的通過比較返回,新添加的將覆蓋集合中原有的,但不會覆蓋。如果這兩個的通過比較返回,新添加的將與集合中原有形成鏈,而且新添加的位于鏈的頭部具體說明繼續看方法的說明。 關于hashCode hashCode的存在主要是用于查找的快捷性,如Hashtable,HashMap等,hashCode是用來在散列存儲結構中確定對象的存儲地址的. 1.hashcode是用來...
摘要:最近看到上面的一篇博客面試必備最常見的面試題全解析講解了關于體系的一些模塊以及面試中的一些常見問題雖然最近沒有要去找工作的需求但是鞏固一下這方面的知識還是很有必要的后面從作者提出的問題進行自我的提問與解答有問題歡迎大家指出基礎部分和的區別我 最近看到CSDN上面的一篇博客 面試必備:《Java最常見的200+面試題全解析》, 講解了關于Java體系的一些模塊以及面試中的一些常見問題; ...
摘要:當容量超過容量負載因子時,進行擴容操作確定何時將沖突的鏈表轉換成紅黑樹用來確何時將紅黑樹轉換成鏈表當鏈表轉換成紅黑樹時,需要判斷數組容量。桶排序核心思想是根據數據規模劃分,個相同大小的區間每個區間為一個桶,桶可理解為容器。 剛剛看到QQ群有人吹Hashmap,一想我啥都不懂,就趕快補了一波。下面分享一下我對Hashmap的理解,主要用于個人備忘。如果有不對,請批評。想要解鎖更多新姿勢?...
摘要:語言通過字節碼的方式,在一定程度上解決了傳統解釋型語言執行效率低的問題,同時又保留了解釋型語言可移植的特點。有針對不同系統的特定實現,,,目的是使用相同的字節碼,它們都會給出相同的結果。項目主要基于捐贈的源代碼。 本文來自于我的慕課網手記:Java編程中那些再熟悉不過的知識點,轉載請保留鏈接 ;) 1. 面向對象和面向過程的區別 面向過程 優點: 性能比面向對象高。因為類調用時需要實例...
閱讀 3836·2021-10-12 10:11
閱讀 3648·2021-09-13 10:27
閱讀 2556·2019-08-30 15:53
閱讀 1986·2019-08-29 18:33
閱讀 2199·2019-08-29 14:03
閱讀 1007·2019-08-29 13:27
閱讀 3327·2019-08-28 18:07
閱讀 800·2019-08-26 13:23