??各位小伙伴們大家好,歡迎來到這個小扎扎的《Java核心技術 卷Ⅰ》筆記專欄,在這個系列專欄中我將記錄淺學這本書所得收獲,鑒于 看到就是學到、學到就是賺到 精神,這波簡直就是血賺
💡涉及的知識點速通
- 🛫 關于Set集合類你都知道什么?
- 🪂 如何理解Set集合元素的無序不可重復?
- 🪂 如何重寫equals和hashCode方法?
- 🪂 HashSet和LinkedHashSet的異同?
- 🪂 TreeSet都需要注意哪些?
- 🪂 集合和數組之間如何相互轉換?
- 🛫 Collection集合類的關系圖
🛫 關于Set集合類你都知道什么?
??我們將實現了Set接口的類稱為是List集合類,List集合類中元素存儲有一個特點:無序、不可重復,Set接口常用的有三個實現類:HashSet、linkedHashSet、TreeSet
🪂 如何理解Set集合元素的無序不可重復?
??無序性: 以HashSet集合為例,HashSet底層創建的是HashMap,而HashMap最主要的數據結構就是散列表,java使用鏈表數組來實現散列表,也就是一種數組加鏈表的結構,在這里數組中的每個元素被稱為是桶(bucket,默認為16)。所謂的元素無序存儲指的是:存儲的元素并不是按照索引順序依次存入數組,而是使用哈希算法也就是將元素的散列碼(hash值)對桶數進行取模運算,得到的結果就是該元素在數組中存儲的索引位置??Object類中定義的有hashCode方法可以獲取該對象對應的散列碼(hash值),又因為Object類是所有類的超類,所以每一個類的對象都能通過hashCode方法獲取到它所對應的散列碼,但是值得注意的是:使用hashCode生成的散列碼不同意味著它們肯定不相等,但是散列碼相等并不就意味著它們一定相等,所以說如果想要判斷它們是否相等需要再進行equals對比,如果equals的結果也為true的話表示它們一定相等
??不可重復性: 這里我們同樣以HashSet集合為例,散列碼相同的元素一定會被分到數組的同一個索引位置進行存儲,此時如果我們再判斷一下新添加的元素與該索引位置上鏈表元素的散列碼是否相等,如果相等再進行equals比較,如果還相等則說明新增元素是個重復元素,這樣的話就可以保證set集合中的元素不會重復了
??元素添加順序: 在jdk7和jdk8中新元素的添加順序也是不一樣的,在jdk7中是新元素 “上位” 指向鏈表中原來最新的元素;而jdk8中則是將新元素 “下位” 放在鏈表的末尾,原來最新的元素指向新元素。可以使用成語 “七上八下” 方便記憶
🪂 如何重寫equals和hashCode方法?
??眾所周知的是,Object類是所有類的超類,所以說如果在不重寫equals和hashCode方法的情況下,set集合判斷添加的是否是重復元素使用的就是Object類中的equals和hashCode方法,但是Object中的equals方法比較的是地址值、hashCode方法是通過地址值生成一個hash值。由此可見,即使自定義類的屬性值都一樣依然會被set集合識別為非重復值,因為他們存儲的地址不同。所以說,自定義類如果使用到hash結構的話,最好重寫equals和hashCode方法
??重寫后的equals和hashCode方法要盡量保持結果一致,也就是說當equals結果為true的時候hashCode的散列碼也要相等,那么如何做到這一點呢?那就是在重寫這兩種方法進行比較或者生成hash值的時候,盡量使用相同的字段,這里可以參考IDEA中默認重寫的equals和hashCode的寫法
🪂 HashSet和LinkedHashSet的異同?
??三者相同點:HashSet、LinkedHashSet和TreeSet都實現了Set接口,所以它們存儲數據的特點都一致,那就是無序、不可重復。而且Set接口中并沒有額外定義新的API方法,也就是說Set集合類中的API都是從Collection接口中繼承過來的
??HashSet是LinkedHashSet的父類,HashSet和LinkedHashSet中可以存儲null元素,而且這兩種set集合都是線程不安全的。除此之外,二者的差距就是LinkedHashSet在HashSet的基礎上又可以將所有的元素按照存入的順序遍歷出來,這并不就意味著LinkedHashSet中存儲的元素就是有序的,而是它在HashSet底層散列表的基礎上又使用雙向鏈表將元素按照順序前后鏈接起來,當遍歷集合元素的時候就可以順著雙向鏈表依次輸出
🪂 TreeSet都需要注意哪些?
??首先TreeSet不可以存儲null元素,否則就會拋出NullPointerException異常。其次TreeSet可以將添加的元素進行排序,但是添加進來的必須是相同類型的元素,否則就會拋出ClassCastException異常??在類型一致的情況下,如果添加的元素是自定義類型的話,必須手動定義排序規則,定義的方式主要有兩種
??第一種是自然排序,即實現Comparable接口重寫compareTo方法,在方法中指定TreeSet集合元素排序的規則,具體使用可以參考下面的截圖??第二種是定制排序,即創建TreeSet集合對象時向參數中傳遞一個comparator對象,該對象應該重寫compare方法并指定排序規則,具體使用可以參考下面的截圖
??從上面兩個例子可以得知一個十分重要的結論:TreeSet集合判斷元素是否重復的規則不再是equals加hashCode方法,而是compareTo方法或者compare方法的返回值,返回值為零則說明元素重復,無法添加到集合中。
🪂 集合和數組之間如何相互轉換?
集合轉數組
??使用Collection接口里的toArray方法,可以將集合轉成一個object數組,而且還可以使用數組對象作為參數指定轉換的數組類型數組轉集合
??數組轉List集合的話可以使用Arrays的asList方法,轉成其他集合的話應該使用循環將數組中的元素依次添加到空集合中,并沒有現成的API可以使用由此可見,Arrays中的asList方法將基本數據類型數組對象當成一個元素轉換成List集合,但是該類型對應的包裝類數組是將數組中的數據對象當成一個元素轉換成List集合
🛫 Collection集合類的關系圖
??至此,我們已經學習了整個Collection集合的常用實現類,在這里我整理了一下Collection集合的關系圖譜供大家參考學習