Java Set接口详细讲解 TreeSet的定制排序和自然排序
Set接口概述
Set實現(xiàn)類之一:HashSet
1 HashSet 是 Set 接口的典型實現(xiàn),大多數(shù)時候使用 Set 集合時都使用這個實現(xiàn)類。
2 HashSet 按 Hash 算法來存儲集合中的元素,因此具有很好的存取、查找、刪除性能。
HashSet 具有以下特點:
不能保證元素的排列順序
HashSet 不是線程安全的
集合元素可以是 null
HashSet 集合判斷兩個元素相等的標(biāo)準(zhǔn):兩個對象通過 hashCode() 方法比較相等,并且兩個對象的 equals() 方法返回值也相等。
對于存放在Set容器中的對象,對應(yīng)的類一定要重寫equals()和hashCode(Object obj)方法,以實現(xiàn)對象相等規(guī)則。即:“相等的對象必須具有相等的散列碼”。
Set實現(xiàn)類之一:HashSet
向HashSet中添加元素的過程:
1 當(dāng)向 HashSet 集合中存入一個元素時,HashSet 會調(diào)用該對象的 hashCode() 方法
來得到該對象的 hashCode 值,然后根據(jù) hashCode 值,通過某種散列函數(shù)決定該對象在 HashSet 底層數(shù)組中的存儲位置。(這個散列函數(shù)會與底層數(shù)組的長度相計算得到在數(shù)組中的下標(biāo),并且這種散列函數(shù)計算還盡可能保證能均勻存儲元素,越是散列分布,該散列函數(shù)設(shè)計的越好)
2 如果兩個元素的hashCode()值相等,會再繼續(xù)調(diào)用equals方法,如果equals方法結(jié)果為true,添加失敗;如果為false,那么會保存該元素,但是該數(shù)組的位置已經(jīng)有元素了,那么會通過鏈表的方式繼續(xù)鏈接。
如果兩個元素的 equals() 方法返回 true,但它們的 hashCode() 返回值不相等,hashSet 將會把它們存儲在不同的位置,但依然可以添加成功。
重寫 hashCode() 方法的基本原則
- 在程序運行時,同一個對象多次調(diào)用 hashCode() 方法應(yīng)該返回相同的值。
- 當(dāng)兩個對象的 equals() 方法比較返回 true 時,這兩個對象的 hashCode() 方法的返回值也應(yīng)相等。
- 對象中用作 equals() 方法比較的 Field,都應(yīng)該用來計算 hashCode 值。
重寫 equals() 方法的基本原則
以自定義的Customer類為例,何時需要重寫equals()? ? 當(dāng)一個類有自己特有的“邏輯相等”概念,當(dāng)改寫equals()的時候,總是
要改寫hashCode(),根據(jù)一個類的equals方法(改寫后),兩個截然不同的實例有可能在邏輯上是相等的,但是,根據(jù)Object.hashCode()方法,它們僅僅是兩個對象。因此,違反了“相等的對象必須具有相等的散列碼”。
結(jié)論:復(fù)寫equals方法的時候一般都需要同時復(fù)寫hashCode方法。通常參與計算hashCode的對象的屬性也應(yīng)該參與到equals()中進(jìn)行計算。
Set實現(xiàn)類之二:LinkedHashSet
- LinkedHashSet 是 HashSet 的子類
- LinkedHashSet 根據(jù)元素的 hashCode 值來決定元素的存儲位置,但它同時使用雙向鏈表維護(hù)元素的次序,這使得元素看起來是以插入順序保存的。
- LinkedHashSet插入性能略低于 HashSet,但在迭代訪問 Set 里的全部元素時有很好的性能。
- LinkedHashSet 不允許集合元素重復(fù)。
Set實現(xiàn)類之三:TreeSet
- TreeSet 是 SortedSet 接口的實現(xiàn)類,TreeSet 可以確保集合元素處于排序狀態(tài)。
- TreeSet底層使用樹結(jié)構(gòu)存儲數(shù)據(jù)
- 新增的方法如下: (了解)
1 Comparator comparator()
2 Object first()
3 Object last()
4 Object lower(Object e)
5 Object higher(Object e)
6 SortedSet subSet(fromElement, toElement) 7SortedSet headSet(toElement)
8SortedSettailSet(fromElement)
TreeSet 兩種排序方法:自然排序和定制排序。默認(rèn)情況下,TreeSet 采用自然排序
排 序—自然排序
自然排序:TreeSet 會調(diào)用集合元素的 compareTo(Object obj) 方法來比較元素之間的大小關(guān)系,然后將集合元素按升序(默認(rèn)情況)排列
如果試圖把一個對象添加到 TreeSet 時,則該對象的類必須實現(xiàn) Comparable 接口
實現(xiàn) Comparable 的類必須實現(xiàn) compareTo(Object obj) 方法,兩個對象即通過compareTo(Object obj) 方法的返回值來比較大小。
向 TreeSet 中添加元素時,只有第一個元素?zé)o須比較compareTo()方法,后面添
加的所有元素都會調(diào)用compareTo()方法進(jìn)行比較。
因為只有相同類的兩個實例才會比較大小,所以向 TreeSet 中添加的應(yīng)該是同一個類的對象。
對于 TreeSet 集合而言,它判斷兩個對象是否相等的唯一標(biāo)準(zhǔn)是:兩個對象通過 compareTo(Object obj) 方法比較返回值。
當(dāng)需要把一個對象放入 TreeSet 中,重寫該對象對應(yīng)的 equals() 方法時,應(yīng)保證該方法與compareTo(Object obj) 方法有一致的結(jié)果:如果兩個對象通過equals() 方法比較返回 true,則通過 compareTo(Object obj) 方法比較應(yīng)返回 0。否則,讓人難以理解。
排 序—定制排序
TreeSet的自然排序要求元素所屬的類實現(xiàn)Comparable接口,如果元素所屬的類沒
有實現(xiàn)Comparable接口,或不希望按照升序(默認(rèn)情況)的方式排列元素或希望按照其它屬性大小進(jìn)行排序,則考慮使用定制排序。定制排序,通Comparator接口來實現(xiàn)。需要重寫compare(T o1,T o2)方法。
利用int compare(T o1,T o2)方法,比較o1和o2的大小:如果方法返回正整數(shù),則表示o1大于o2;如果返回0,表示相等;返回負(fù)整數(shù),表示o1小于o2。
要實現(xiàn)定制排序,需要將實現(xiàn)Comparator接口的實例作為形參傳遞給TreeSet的構(gòu)造器。
此時,仍然只能向TreeSet中添加類型相同的對象。否則發(fā)生ClassCastException異常。
使用定制排序判斷兩個元素相等的標(biāo)準(zhǔn)是:通過Comparator比較兩個元素返回了0。
User中的comareTo方法
//按照姓名從小到大排序@Overridepublic int compareTo(Object o) {if(o instanceof User){User user = (User)o;//return this.name.compareTo(user.name);int compare = this.name.compareTo(user.name);if(compare!=0){return compare;}else{return Integer.compare(this.age,user.age);}}else{throw new RuntimeException("類型不匹配!!");}} 新人創(chuàng)作打卡挑戰(zhàn)賽發(fā)博客就能抽獎!定制產(chǎn)品紅包拿不停!總結(jié)
以上是生活随笔為你收集整理的Java Set接口详细讲解 TreeSet的定制排序和自然排序的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: TCP 协议状态解析
- 下一篇: 利用递归的方法求最大公约数和最小公倍数(