一、概述
LinkedHashSet類也是集合家族中的一員,LinkedHashSet類是Set類的一個實現,具有set集合不重複的特點,同時具有可預測的迭代順序,也就是我們插入的順序。那麼具體如何實現,請看源碼解析。
二、源碼解析
1. 類的聲明
public class LinkedHashSet<E>
extends HashSet<E>
implements Set<E>, Cloneable, java.io.Serializable
LinkedHashSet類繼承自HashSet類,同時實現了Set接口、Cloneable接口以及Serializable接口,這個結構和ArrayList類的結構很相似,我們仔細分析一下:
* 繼承HashSet類,可以自己實現父類的方法(雖然源碼裏沒有,萬一以後有呢)。
* 實現Set接口,一是爲了增加可讀性,清晰看到實現的接口,二是降低維護成本,如果HashSet類不實現Set了,LinkedHashSet類也不受影響。
* Cloneable接口也是克隆標記接口,表示此類可以被克隆,此類的實例可以調用clone()方法;未實現Cloneable接口的類的實例調用clone()方法會報錯,在Object類中已經定義。
* Serializable接口是序列化標記接口,表示此類可以被序列化到內存中。目的是爲類可持久化,比如在網絡傳輸或本地存儲,爲系統的分佈和異構部署提供先決條件。
2. 構造函數
// 傳入容量和裝載因子
public LinkedHashSet(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor, true);
}
// 只傳入容量, 裝載因子默認爲0.75
public LinkedHashSet(int initialCapacity) {
super(initialCapacity, .75f, true);
}
// 使用默認容量16, 默認裝載因子0.75
public LinkedHashSet() {
super(16, .75f, true);
}
// 將集合c中的所有元素添加到LinkedHashSet中
// 好奇怪, 這裏計算容量的方式又變了
// HashSet中使用的是Math.max((int) (c.size()/.75f) + 1, 16)
// 這一點有點不得其解, 是作者偷懶?
public LinkedHashSet(Collection<? extends E> c) {
super(Math.max(2*c.size(), 11), .75f, true);
addAll(c);
}
LinkedHashSet類所有的構造方法都是調用了HashSet的構造方法,而HashSet中又調用了LinkedHashMap類中的構造方法。源碼如下:
//HashSet類中的構造函數
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
map = new LinkedHashMap<>(initialCapacity, loadFactor);
}
//LinkedHashMap類中的構造函數
public LinkedHashMap(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor);
accessOrder = false;
}
這樣我們就能清晰的瞭解到,LinkedHashSet類創建的實例是遵循了LinkedHashMap中排序規則accessOrder爲false, 也就是會按照插入順序進行排序(在創建新節點的時候,把該節點放到了尾部) 。
3. 迭代器
// 可分割的迭代器, 主要用於多線程並行迭代處理時使用
@Override
public Spliterator<E> spliterator() {
return Spliterators.spliterator(this, Spliterator.DISTINCT | Spliterator.ORDERED);
}
三、總結
LinkedHashSet類是我們瞭解集合大家庭族譜中的一個環節,LinkedHashSet類重要的知識點有如下幾點:
1. LinkedHashSet的底層使用LinkedHashMap存儲元素。
2. LinkedHashSet是有序的,它是按照插入的順序排序的,不支持按元素訪問順序排序。
敬請期待《 我的jdk源碼(十九):TreeMap 》。
更多精彩內容,敬請掃描下方二維碼,關注我的微信公衆號【Java覺淺】,獲取第一時間更新哦!