java基礎:HashSet/LinkedHashSet/TreeSet — 原始碼分析

Hiway發表於2019-01-04

其他更多java基礎文章:
java基礎學習(目錄)


Set集合的底層都是使用相對應的Map。HashSet底層是HashMap,LinkedHashSet底層是使用LinkedHashMap,TreeSet底層是使用TreeMap。都相對簡單,所以就放在一篇文章裡講解了。只簡單講一下HashSet的原始碼,因為其他兩者大同小異。

HashSet

資料結構和基礎欄位

    private transient HashMap<E,Object> map;

    private static final Object PRESENT = new Object();
複製程式碼

顯而易見,hashSet的底層和方法就是使用hashmap。Set實現值不重複的原理就是在儲存值到底層hashmap裡的時候,儲存為key值,value值為常量PRESENT。具體可以看下面方法講解。

方法細節

構造方法

    public HashSet() {
        map = new HashMap<>();
    }
    public HashSet(Collection<? extends E> c) {
        map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
        addAll(c);
    }
    
    //自己初始化容量和載入因子的大小
    public HashSet(int initialCapacity, float loadFactor) {
        map = new HashMap<>(initialCapacity, loadFactor);
    }
    
    //初始化容量大小,載入因子用預設的
    public HashSet(int initialCapacity) {
        map = new HashMap<>(initialCapacity);
    }
複製程式碼

簡單的構造方法,就不闡述了。

add方法

//這個方法就可以得知HashSet新增的元素是不能夠重複的,原因是什麼呢,set將每次新增的元素度是通過map中的key來儲存,當有
//相同的key時,也就是新增了相同的元素,那麼map會講value給覆蓋掉,而key還是原來的key,所以,這就是set不能夠重複的原因。這個方法的PRESENT可以看下面的註釋,
//返回值的式子的意思很好理解,map中增加元素是先通過key查詢有沒有相同的key值,如果有,則覆蓋value,返回oldValue。沒有
//,則建立一個新的entry,並且返回null值。如果key等於null,也會返回null值。所以return會有一個==null的判斷

    public boolean add(E e) {
        return map.put(e, PRESENT)==null;
    }
複製程式碼

remove方法

//set通過判斷刪除元素是否為常量PRESENT,來確定是否成功刪除
    public boolean remove(Object o) {
        return map.remove(o)==PRESENT;
    }

    //hashmap中的remove方法
    public V remove(Object key) {
        Entry<K,V> e = removeEntryForKey(key);
        return (e == null ? null : e.value);
    }
複製程式碼

總結

  1. 元素沒有順序(現在知道為什麼沒有順序了把,因為底層用的是HashMap,HashMap本身中的元素度沒有順序,那麼HashSet更不可能有了)
  2. 元素不能重複,集合元素可以是null,但只能放入一個null(這個也很好理解了,因為HashSet中存放的元素,度是當作HashMap的key來使用,HashMap中key是不能相同的,所以HashSet的元素也不能重複了)  
  3. 非執行緒安全。
  4. HashSet使用成員物件來計算hashcode值,對於兩個物件來說hashcode可能相同,所以equals()方法用來判斷物件的相等性,如果兩個物件不同的話,那麼返回false。所以如果儲存自定義物件,需要重寫自定義物件的hashcode方法和equals方法。
  5. TreeSet可以確保集合元素處於排序狀態。TreeSet支援兩種排序方式,自然排序 和定製排序,其中自然排序為預設的排序方式。
  6. LinkedHashSet集合同樣是根據元素的hashCode值來決定元素的儲存位置,但是它同時使用連結串列維護元素的次序,當遍歷該集合時候,LinkedHashSet將會以元素的新增順序訪問集合的元素。LinkedHashSet建立的時候只會建立以插入順序排序的LinkedHashMap。

相關文章