List去重为什么要写equals(),hashCode()方法
一,各個(gè)集合的特點(diǎn):
- Collection(集合):容器,用于存放對(duì)象(引用類型。基本類型需要自動(dòng)裝箱)? ?
- List(列表):元素有序,元素可以重復(fù) (有索引)。 通過(guò)元素的equals()方法判斷是否重復(fù)。??
- Set(集):元素?zé)o序,不可重復(fù) (沒(méi)有索引)。 遍歷只能用Iterator迭代器和增強(qiáng)for, 不能使用普通for遍歷。?
- ArrayList(數(shù)組列表): 查詢快,增刪慢。? ?
- LinkedList(鏈表): 查詢慢,增刪快。
- HashSet(哈希表): 查詢快,增刪慢。 (底層其實(shí)就是Map) 。 存放的引用類型需重寫hashCode()和equals()方法。?
- LinkedHashSet(哈希鏈表): 查詢慢,增刪快。 有序的,存放順序和取出順序一致。
1.1,為什么要去重:
- 在我們開(kāi)發(fā)中,我們所讀取的數(shù)據(jù)難免會(huì)有重復(fù)數(shù)據(jù),我們需要的則是不重復(fù)數(shù)據(jù)的引用,所以需要對(duì)數(shù)據(jù)進(jìn)行去重,
- 而基本數(shù)據(jù)類型的去重比較好去重而引用數(shù)據(jù)類型呢,因?yàn)橐袛鄅ashCode運(yùn)算是否相等,還有equals()是否相等,所以需要去重操作,
- 我們以一個(gè)list集合為例,在該例中,我們將User實(shí)體類中姓名和電話號(hào)碼作為判斷該對(duì)象重復(fù)的標(biāo)識(shí),在User的實(shí)體類中我們重寫
- 這兩個(gè)方法如下:
- 以上實(shí)體類中,我們?cè)趀quals()方法中取出該對(duì)象的name與region和performance這三個(gè)屬性值去判斷比較,然后在重寫的hashCode()
- 方法中返回這三個(gè)屬性值得equals對(duì)象地址值。
1.2,去重操作步驟:
1 package com.example.arraylist; 2 3 import java.util.ArrayList; 4 import java.util.Iterator; 5 import java.util.List; 6 import com.example.pojo.User; 7 8 /** 9 * @author Administrator 10 * 思路: 11 * 1.先對(duì)其文本文本進(jìn)行添加,添加到List<User>中 12 * 2.把List<User>用迭代器進(jìn)行迭代 13 * 3.創(chuàng)建一個(gè)新的集合,用來(lái)存儲(chǔ)不重復(fù)的元素 14 * 4.用while(it.hasNext())有多少元素就循環(huán)多少次 15 * 4.判斷新的集合是否有舊的元素如果沒(méi)有則進(jìn)行添加 16 */ 17 public class ListUserRepeat { 18 public static void main(String[] args) { 19 String string="張三,河北,90\n"+ 20 "張三,河南,92\n"+ 21 "李四,湖北,80\n"+ 22 "王五,山西,88\n"+ 23 "張三,河北,90\n"+ 24 "李四,湖北,80\n"+ 25 "馬六,山東,77\n"; 26 List<User> list = new ArrayList<>(); 27 String[] split = string.split("\n"); 28 for(String spl : split) { 29 String[] split2 = spl.split(","); 30 list.add(new User(split2[0], split2[1],Integer.parseInt(split2[2]))); 31 } 32 Iterator<User> it = list.iterator(); 33 List<User> listOne = new ArrayList<>(); 34 while(it.hasNext()) { 35 Object object = it.next(); 36 if(!listOne.contains(object)) { 37 listOne.add((User) object); 38 } 39 } 40 for (User user : listOne) { 41 System.out.println(user); 42 } 43 } 44 }運(yùn)行這段代碼之后,就會(huì)很明顯的發(fā)現(xiàn),list中重復(fù)的用戶名,地區(qū),都相同的對(duì)象就被會(huì)認(rèn)為是重復(fù)的元素而刪除掉,很明顯運(yùn)行結(jié)果已經(jīng)達(dá)到我們的目的。
二,說(shuō)一下為什么需要重寫equals()方法和hashChode方法():
- 一般情況下我們重寫equals()方法的時(shí)候還要重寫hashChode()方法,但是我們用的是list所以不用重寫hashCode,大家不妨
- 可以試試上面的例子,在實(shí)體類將重寫的equals()方法注釋掉,再運(yùn)行程序,這時(shí)就會(huì)發(fā)現(xiàn)運(yùn)行結(jié)果并不是我們剛剛得到的結(jié)果,(圖中 我用的是list集合,
- 不是set集合,list集合只需要重寫equals()方法就行,而set集合則equals()和hashCode()方法都需要重寫)
2.1,String類中的equals()方法的源碼如下:
1 public boolean equals(Object anObject) { 2 if (this == anObject) { 3 return true; 4 } 5 if (anObject instanceof String) { 6 String anotherString = (String)anObject; 7 int n = value.length; 8 if (n == anotherString.value.length) { 9 char v1[] = value; 10 char v2[] = anotherString.value; 11 int i = 0; 12 while (n-- != 0) { 13 if (v1[i] != v2[i]) 14 return false; 15 i++; 16 } 17 return true; 18 } 19 } 20 return false; 21 }通過(guò)觀察equals()方法的源碼我們可以看出,該方法去比較兩個(gè)對(duì)象時(shí),首先先去判斷兩個(gè)對(duì)象是否具有相同的地址,如果是同一個(gè)對(duì)象的引用,則直接放回true;如果地址不一樣,則證明不是引用同一個(gè)對(duì)象,接下來(lái)就是挨個(gè)去比較兩個(gè)字符串對(duì)象的內(nèi)容是否一致,完全相等返回true,否則false。
2.2,String類中hashCode()方法的源碼如下:
1 public int hashCode() { 2 int h = hash; 3 if (h == 0 && value.length > 0) { 4 char val[] = value; 5 6 for (int i = 0; i < value.length; i++) { 7 h = 31 * h + val[i]; 8 } 9 hash = h; 10 } 11 return h; 12 }以上是String類中重寫的hashCode()方法,在Object類中的hashCode()方法是返回對(duì)象的32位JVM內(nèi)存地址,也就是說(shuō)如果我們不去重寫該方法,將會(huì)返回該對(duì)象的32位JVM內(nèi)存地址,以上我們測(cè)試的例子中,當(dāng)注釋掉重寫的hashCode()方法時(shí),這時(shí)默認(rèn)返回對(duì)象的32JVM中的地址,兩個(gè)不同的對(duì)象地址顯然是不同的,我們?cè)诒容^時(shí),雖然通過(guò)重寫的equals()方法比較出來(lái)name和phoneNumber值是相同的,但是默認(rèn)的hashCode()方法返回的值他們并不是同一個(gè)對(duì)象,所以我們通常要將hashCode()方法與equals()方法一起重寫,以維護(hù)hashCode方法的常規(guī)協(xié)定,該協(xié)定聲明相等對(duì)象必須具有相等的哈希碼。
總結(jié):
用白話說(shuō),通過(guò)hashCode判斷對(duì)象是否放在同一個(gè)桶里,先確定他們?cè)谝粋€(gè)桶里面,然后再通過(guò)equals方法去判斷這個(gè)桶里的對(duì)象是不是相同的。
轉(zhuǎn)載于:https://www.cnblogs.com/joeyJss/p/10172147.html
總結(jié)
以上是生活随笔為你收集整理的List去重为什么要写equals(),hashCode()方法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 再见Spring Security!推荐
- 下一篇: 计算机是如何启动的