1. 程式人生 > >Collection容器家族(HashSet原始碼詳解)

Collection容器家族(HashSet原始碼詳解)

一、在Collection集合體系中的位置及概述

        HashSet繼承自AbstractSet抽象類,實現了Cloneable、Serializable介面,顯示的實現了Set介面。至於為什麼顯示的實現Set介面,我前面的文章講過。

       HashSet而言,它是基於HashMap實現的,本質上講HashSet底層實現是HashMap的封裝類物件,HashSet的所有操作都是基於HashMap實現。使用HashMap來儲存所有元素,因此HashSet 的實現比較簡單,相關HashSet的操作,基本上都是直接呼叫底層HashMap的相關方法來完成,HashSet原始碼非常簡單。

       HashSet類,執行緒不安全,允許null鍵;

HashSet中的使用HashMap的方法,如果想要學習HashMap,請參見我的另一篇部落格

二、成員變數

    // HashMap用於儲存操作,HashSet底層封裝類物件
    private transient HashMap<E,Object> map;

    // Dummy value to associate with an Object in the backing Map
    // 與支援Map中的Object關聯的虛擬值
    private static final Object PRESENT = new Object();

        僅有兩個成員變數,map為HashSet底層的封裝類物件,PRESENT為map中所有鍵值對的值。HashSet使用封裝類物件HashMap的鍵儲存元素,而其所有的值都使用PRESENT。

三、構造方法

    // 無參構造
    // 建立封裝的HashMap
    public HashSet() {
        map = new HashMap<>();
    }

    // 使用集合作為引數構造本集合
    public HashSet(Collection<? extends E> c) {
        // 建立封裝物件HashMap, 引數為c的大小和16中最大的值
        map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
        // 使用AbstractCollection的addAll方法,它是迴圈遍歷呼叫add方法實現新增元素
        addAll(c);
    }

    // 帶參構造
    // 指定初始容量和載入因子
    public HashSet(int initialCapacity, float loadFactor) {
        map = new HashMap<>(initialCapacity, loadFactor);
    }

    // 帶參構造
    // 指定處事容量
    public HashSet(int initialCapacity) {
        map = new HashMap<>(initialCapacity);
    }

    // 帶參構造
    HashSet(int initialCapacity, float loadFactor, boolean dummy) {
        map = new LinkedHashMap<>(initialCapacity, loadFactor);
    }

四、常用API

1.新增元素

    public boolean add(E e) {
        // 呼叫HashMap的put方法新增元素
        return map.put(e, PRESENT)==null;
    }

2.刪除元素

    // 刪除所有元素
    public void clear() {
        // 呼叫的HashMap的clear方法
        map.clear();
    }

    // 移除指定的元素o
    public boolean remove(Object o) {
        // 呼叫HashMap的remove方法
        return map.remove(o)==PRESENT;
    }

3.遍歷

     */
    // 獲取迭代器
    public Iterator<E> iterator() {
        // 獲取HashMap的鍵的Set集合的迭代器
        return map.keySet().iterator();
    }

4.獲取元素個數

    public int size() {
        // 呼叫HashMap的size方法獲取
        return map.size();
    }

5.判斷是否包含指定鍵

    public boolean contains(Object o) {
        // 呼叫HashMap的containsKey獲取
        return map.containsKey(o);
    }

6.判斷是否為空

    public boolean isEmpty() {
        // 呼叫HashMap的isEmpty
        return map.isEmpty();
    }

五、總結

        到這裡HashSet就結束了,它的所有方法都是基於HashMap。