equals與hashcode的關係
1、hashcode方法和equals方法都是Object類中的方法,Object類對equals方法進行了定義,比較的是兩個物件的引用來確定比較的物件是否是同一個物件;
而Object類沒有對hashcode方法進行定義。
2、當物件類需要進行比較或者插入到集合中時,需要重寫equals方法和hashcode方法,同時要保持兩個方法返回結果一致
3、equals方法一般用於物件例項內容的比較,而hashcode方法一般用於集合中用到;
集合使用步驟:
(1)物件放入到 集合中時,首先需要比較放入物件的hashcode值是否與原有集合中的元素重複(hashcode方法),如果不相等就直接放入到集合中;
(2)如果hashcode值相等,則再次比較equals方法,如果該方法返回值不一致就可以插入到集合中,但如果也相等,則不能插入到集合中
注:一般hashcode方法主要用在使用hash結構的類中,比如HashSet、HashTable、HashMap中等;在hash結構中還存在同一個hash值對應的桶的結構(實際上是一個數組),如果hash值相同,然後equals方法不同,則會放入到同一個位置的桶結構中。
具體程式碼:
測試程式碼:(沒有重寫equals方法)
LinkedList<Person> list = new LinkedList<>();
Set<Person> set = new HashSet<>();
Person p1 = new Person();
Person p2 = new Person();
p1.setAge(12);
p1.setName("p");
p2.setAge(12);
p2.setName("p");
System.out.println("p1 == p2:" + (p1 == p2));// == 比較的是其值是否相同
System.out.println("p1 equals p2" + (p1.equals(p2)));// 呼叫Object的equals,判斷是否是同一個物件
list.add(p1);
list.add(p2);
set.add(p2);
set.add(p1);
System.out.println(list.size());
System.out.println(set.size());
結果:
p1 == p2:false
p1 equals p2false
2
2
程式碼測試:(重寫equals方法)
p1 == p2:false
p1 equals p2false
2
2
程式碼測試:(重寫hashcode方法)
p1 == p2:false
p1 equals p2 :true
2
2
程式碼測試:(兩個都重寫)
p1 == p2:false
p1 equals p2 :true
2
1
另外,說到hashcode方法了,就再說一下HashSet集合和HashMap集合的淵源:
HashSet集合在底層也是使用HashMap來實現元素的儲存,只是將元素本身作為key,而value是一個Object物件(未知);而HashMap集合在底層是通過一個泛型動態陣列來儲存資料的:transient Entry<K,V>[] table = (Entry<K,V>[]) EMPTY_TABLE;
這個泛型動態陣列初始化大小是16,,負載因子是0.75,當插入的元素個數達到陣列大小*0.75時,
泛型陣列每次增長都是變為原來的二倍;(利用空間換時間來提高讀取速度)
同時泛型動態陣列中又包含桶的結構,類似於c中的連結串列陣列,桶中儲存的都是hash值相同的元素;
如圖: