Set接口Set接口是Collection的子接口,set接口沒有提供額外的方法。
Set 集合不允許包含相同的元素,如果試把兩個(gè)相同的元素加入同一個(gè) Set 集合中,則添加操作失敗。
Set 判斷兩個(gè)對(duì)象是否相同不是使用 == 運(yùn)算符,而是根據(jù) equals 方法。因此存放到Set集合中的元素一定要注意equals方法的重寫。
Set的常用實(shí)現(xiàn)類有:HashSet、TreeSet、LinkedHashSet。
HashSet1、概述
HashSet 是 Set 接口的典型實(shí)現(xiàn),大多數(shù)時(shí)候使用 Set 集合時(shí)都使用這個(gè)實(shí)現(xiàn)類。
HashSet 按 Hash 算法來存儲(chǔ)集合中的元素,因此具有很好的存取和查找性能。
HashSet 集合判斷兩個(gè)元素相等的標(biāo)準(zhǔn):兩個(gè)對(duì)象通過 hashCode() 方法比較相等,并且兩個(gè)對(duì)象的 equals() 方法返回值也相等。
當(dāng)向 HashSet 集合中存入一個(gè)元素時(shí),HashSet 會(huì)調(diào)用該對(duì)象的 hashCode() 方法來得到該對(duì)象的 hashCode 值,然后根據(jù) hashCode 值,通過某種散列函數(shù)決定該對(duì)象在 HashSet 中的存儲(chǔ)位置。(這個(gè)散列函數(shù)會(huì)與底層數(shù)組的長度相計(jì)算得到在數(shù)組中的下標(biāo),并且這種散列函數(shù)計(jì)算還盡可能保證能均勻存儲(chǔ)元素,越是散列分布,該散列函數(shù)設(shè)計(jì)的越好)
如果兩個(gè)元素的hashCode()值相等,會(huì)再繼續(xù)調(diào)用equals方法,如果equals方法結(jié)果為true,添加失敗,如果為false,那么會(huì)保存該元素,但是該數(shù)組的位置已經(jīng)有元素了,那么會(huì)通過鏈表的方式繼續(xù)鏈接。
HashSet 具有以下特點(diǎn):
不能保證元素的排列順序
HashSet 不是線程安全的
集合元素可以有一個(gè)是 null
底層也是數(shù)組,初始容量為16,當(dāng)如果使用率超過0.75,(16*0.75=12)就會(huì)擴(kuò)大容量為原來的2倍。(16擴(kuò)容為32,依次為64,128….等)
結(jié)論:存放到Set集合中的元素一定要注意equals和hashcode方法的重寫。
2、hashCode和equals方法
重寫equals()方法的原則:
對(duì)稱性:如果x.equals(y)返回是“true”,那么y.equals(x)也應(yīng)該返回是“true”。
自反性:x.equals(x)必須返回是“true”。
類推性:如果x.equals(y)返回是“true”,而且y.equals(z)返回是“true”,那么z.equals(x)也應(yīng)該返回是“true”。
一致性:如果x.equals(y)返回是“true”,只要x和y內(nèi)容一直不變,不管你重復(fù)x.equals(y)多少次,返回都是“true”。
任何情況下,x.equals(null),永遠(yuǎn)返回是“false”;x.equals(和x不同類型的對(duì)象)永遠(yuǎn)返回是“false”。
重寫 hashCode() 方法的基本原則
在程序運(yùn)行時(shí),同一個(gè)對(duì)象多次調(diào)用 hashCode() 方法應(yīng)該返回相同的值
當(dāng)兩個(gè)對(duì)象的 equals() 方法比較返回 true 時(shí),這兩個(gè)對(duì)象的 hashCode() 方法的返回值也應(yīng)相等
對(duì)象中用作 equals() 方法比較的屬性Field,都應(yīng)該用來計(jì)算 hashCode 值
LinkedHashSetLinkedHashSet 是 HashSet 的子類
LinkedHashSet 根據(jù)元素的 hashCode 值來決定元素的存儲(chǔ)位置,但它同時(shí)使用鏈表維護(hù)元素的次序,這使得元素看起來是以插入順序保存的。
LinkedHashSet插入性能略低于 HashSet,但在迭代訪問 Set 里的全部元素時(shí)有很好的性能。
LinkedHashSet 不允許集合元素重復(fù)。
TreeSetTreeSet 是 SortedSet 接口的實(shí)現(xiàn)類,TreeSet 可以確保集合元素處于排序狀態(tài)。
TreeSet 兩種排序方法:自然排序和定制排序。默認(rèn)情況下,TreeSet 采用自然排序。
1、自然排序
TreeSet 會(huì)調(diào)用集合元素的 compareTo(Object obj) 方法來比較元素之間的大小關(guān)系,然后將集合元素按升序排列,如果試圖把一個(gè)對(duì)象添加到 TreeSet 時(shí),則該對(duì)象的類必須實(shí)現(xiàn) Comparable 接口。實(shí)現(xiàn) Comparable 的類必須實(shí)現(xiàn) compareTo(Object obj) 方法,兩個(gè)對(duì)象即通過 compareTo(Object obj) 方法的返回值來比較大小。
向 TreeSet 中添加元素時(shí),只有第一個(gè)元素?zé)o須比較compareTo()方法,后面添加的所有元素都會(huì)調(diào)用compareTo()方法進(jìn)行比較。
因?yàn)橹挥邢嗤惖膬蓚€(gè)實(shí)例才會(huì)比較大小,所以向 TreeSet 中添加的應(yīng)該是同一個(gè)類的對(duì)象
對(duì)于 TreeSet 集合而言,它判斷兩個(gè)對(duì)象是否相等的唯一標(biāo)準(zhǔn)是:兩個(gè)對(duì)象通過 compareTo(Object obj) 方法比較返回值
當(dāng)需要把一個(gè)對(duì)象放入 TreeSet 中,重寫該對(duì)象對(duì)應(yīng)的 equals() 方法時(shí),應(yīng)保證該方法與 compareTo(Object obj) 方法有一致的結(jié)果:如果兩個(gè)對(duì)象通過 equals() 方法比較返回 true,則通過 compareTo(Object obj) 方法比較應(yīng)返回 0。否則讓人難以理解。
Comparable 的典型實(shí)現(xiàn):
BigDecimal、BigInteger 以及所有的數(shù)值型對(duì)應(yīng)的包裝類:按它們對(duì)應(yīng)的數(shù)值大小進(jìn)行比較
Character:按字符的 unicode值來進(jìn)行比較
Boolean:true 對(duì)應(yīng)的包裝類實(shí)例大于 false 對(duì)應(yīng)的包裝類實(shí)例
String:按字符串中字符的 unicode 值進(jìn)行比較
Date、Time:后邊的時(shí)間、日期比前面的時(shí)間、日期大
2、定制排序
TreeSet的自然排序是根據(jù)集合元素的大小,進(jìn)行元素升序排列。如果需要定制排序,比如降序排列,可通過Comparator接口的幫助。需要重寫compare(T o1,T o2)方法。利用int compare(T o1,T o2)方法,比較o1和o2的大?。喝绻椒ǚ祷卣麛?shù),則表示o1大于o2;如果返回0,表示相等;返回負(fù)整數(shù),表示o1小于o2。
要實(shí)現(xiàn)定制排序,需要將實(shí)現(xiàn)Comparator接口的實(shí)例作為形參傳遞給TreeSet的構(gòu)造器。
此時(shí),仍然只能向TreeSet中添加類型相同的對(duì)象。否則發(fā)生ClassCastException異常。
使用定制排序判斷兩個(gè)元素相等的標(biāo)準(zhǔn)是:通過Comparator比較兩個(gè)元素返回了0。
當(dāng)使用具有與 equals 不一致的強(qiáng)行排序能力的 Comparator 對(duì)有序 set(或有序映射)進(jìn)行排序時(shí),應(yīng)該小心謹(jǐn)慎。假定一個(gè)帶顯式 Comparator c 的有序 set(或有序映射)與從 set S 中抽取出來的元素(或鍵)一起使用。如果 c 強(qiáng)行對(duì) S 進(jìn)行的排序是與 equals 不一致的,那么有序 set(或有序映射)將是行為“怪異的”。
3、結(jié)論
1.放到TreeSet集合中的元素必須是同一個(gè)類型的元素
2.放到TreeSet集合中的元素必須實(shí)現(xiàn)Comparable接口,重寫compareTo(Object obj)方法,并且需要使得equals方法的與compareTo方法結(jié)果一直,即如果兩個(gè)對(duì)象通過 equals() 方法比較返回 true,則通過 compareTo(Object obj) 方法比較應(yīng)返回 0。
3.TreeSet的自然排序是根據(jù)集合元素的大小,進(jìn)行元素升序排列。如果需要定制排序,比如降序排列,可以將實(shí)現(xiàn)Comparator接口的實(shí)例作為形參傳遞給TreeSet的構(gòu)造器,那么添加元素時(shí),將調(diào)用compare(T o1,T o2)方法作為排序依據(jù)。同時(shí)也應(yīng)該注意equals方法與compare(T o1,T o2)方法的結(jié)果一致。
相關(guān)文章:
java集合的遍歷
java集合List接口
java集合Collection接口
java之?dāng)?shù)據(jù)格式化
Java異常處理的概述