JDK 1.7源碼閱讀筆記(七)集合類之HashMap

前言

  HashMap一直是我的一個心病,因爲在面試的時候HashMap是個出現頻率高發點,不管是知識點,還是現場編程,而且自己當時答得不好,今天就回歸到源碼,真正探究下HashMap的底層實現,去獲知它的特性。

特性描述

  (1)基於哈希表的 Map 接口的實現。此實現提供所有可選的映射操作,並允許使用 null 值和 null 鍵。(除了非同步和允許使用 null 之外,HashMap 類與 Hashtable 大致相同。)此類不保證映射的順序,特別是它不保證該順序恆久不變。

  (2)此實現假定哈希函數將元素適當地分佈在各桶之間,可爲基本操作(get 和 put)提供穩定的性能。迭代 collection 視圖所需的時間與 HashMap 實例的“容量”(桶的數量)及其大小(鍵-值映射關係數)成比例。所以,如果迭代性能很重要,則不要將初始容量設置得太高(或將加載因子設置得太低)。

  (3)HashMap 的實例有兩個參數影響其性能:初始容量加載因子。容量 是哈希表中桶的數量,初始容量只是哈希表在創建時的容量。加載因子 是哈希表在其容量自動增加之前可以達到多滿的一種尺度。當哈希表中的條目數超出了加載因子與當前容量的乘積時,則要對該哈希表進行 rehash 操作(即重建內部數據結構),從而哈希表將具有大約兩倍的桶數。

  通常,默認加載因子 (.75) 在時間和空間成本上尋求一種折衷。加載因子過高雖然減少了空間開銷,但同時也增加了查詢成本(在大多數 HashMap 類的操作中,包括 get 和 put 操作,都反映了這一點)。在設置初始容量時應該考慮到映射中所需的條目數及其加載因子,以便最大限度地減少 rehash 操作次數。如果初始容量大於最大條目數除以加載因子,則不會發生 rehash 操作。

  如果很多映射關係要存儲在 HashMap 實例中,則相對於按需執行自動的 rehash 操作以增大表的容量來說,使用足夠大的初始容量創建它將使得映射關係能更有效地存儲。

  (4)注意,此實現不是同步的。如果多個線程同時訪問一個哈希映射,而其中至少一個線程從結構上修改了該映射,則它必須 保持外部同步。(結構上的修改是指添加或刪除一個或多個映射關係的任何操作;僅改變與實例已經包含的鍵關聯的值不是結構上的修改。)這一般通過對自然封裝該映射的對象進行同步操作來完成。如果不存在這樣的對象,則應該使用 Collections.synchronizedMap 方法來“包裝”該映射。最好在創建時完成這一操作,以防止對映射進行意外的非同步訪問,如下所示:

Map m = Collections.synchronizedMap(new HashMap(…));由所有此類的“collection 視圖方法”所返回的迭代器都是快速失敗 的:在迭代器創建之後,如果從結構上對映射進行修改,除非通過迭代器本身的 remove 方法,其他任何時間任何方式的修改,迭代器都將拋出 ConcurrentModificationException。因此,面對併發的修改,迭代器很快就會完全失敗,而不冒在將來不確定的時間發生任意不確定行爲的風險。

  注意,迭代器的快速失敗行爲不能得到保證,一般來說,存在非同步的併發修改時,不可能作出任何堅決的保證。快速失敗迭代器盡最大努力拋出 ConcurrentModificationException。因此,編寫依賴於此異常的程序的做法是錯誤的,正確做法是:迭代器的快速失敗行爲應該僅用於檢測程序錯誤。

描述

  上面這些基本都是JDK中對HashMap的描述,下面這段描述是我對於HashMap的理解,如果有錯誤還望指正,謝謝!
  (1)HashMap的內部存儲結構其實是數組和鏈表的結合。當實例化一個HashMap時,系統會創建一個長度爲Capacity的Entry數組,這個長度被稱爲容量(Capacity),在這個數組中可以存放元素的位置我們稱之爲“桶”(bucket),每個bucket都有自己的索引,系統可以根據索引快速的查找bucket中的元素。
每個bucket中存儲一個元素,即一個Entry對象,但每一個Entry對象可以帶一個引用變量,用於指向下一個元素,因此,在一個桶中,就有可能生成一個Entry鏈。
  (2) 在存儲一對值時(Key—->Value對),實際上是存儲在一個Entry的對象e中,程序通過key計算出Entry對象的存儲位置。換句話說,Key—->Value的對應關係是通過key—-Entry—-value這個過程實現的,所以就有我們表面上知道的key存在哪裏,value就存在哪裏。
  (3)HashMap的衝突處理是用的是鏈地址法, 將所有哈希地址相同的記錄都鏈接在同一鏈表中。也就是說,當HashMap中的每一個bucket裏只有一個Entry,不發生衝突時,Hashmap是一個數組,根據索引可以迅速找到Entry,但是,當發生衝突時,單個的bucket裏存儲的是一個Entry鏈,系統必須按順序遍歷每個Entry,直到找到爲止。爲了減少數據的遍歷,衝突的元素都是直接插入到第一個Entry後面的,所以,最早放入bucket中的Entry,位於Entry鏈中的最末端。這從put(K key,V value)中也可以看出,在同一個bucket存儲Entry鏈的情況下,新放入的Entry總是位於bucket中。
  (4)對於Map接口來說,其本身是不能直接使用迭代(Iteraor)進行輸出的,因爲Map接口的中的每個位置存放的是一對值(key—->value),而Iterator中每次只能找到一個值,如果要通過迭代的方法進行輸出,主要分爲以下幾步:
  1、將Map接口的實例通過Set entrySet();方法變爲Set接口對象;
  2、通過Set接口實例爲Iterator實例化
  3、通過Iterator迭代輸出,輸出的每個內容都是Map.Entry的對象
  4、通過Map.Entry進行key—value的分離
  

源碼

//繼承了AbstractMap抽象類,實現了Map接口  
public class HashMap<K,V>  
    extends AbstractMap<K,V>  
    implements Map<K,V>, Cloneable, Serializable  
{  

    //默認初始化化容量,即16  
    static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; 

    //最大容量,即2的30次方  
    static final int MAXIMUM_CAPACITY = 1 << 30;  

    //默認裝載因子  
    static final float DEFAULT_LOAD_FACTOR = 0.75f;  

    //HashMap內部的存儲結構是一個數組,此處數組爲空,即沒有初始化之前的狀態  
    static final Entry<?,?>[] EMPTY_TABLE = {};  

    //空的存儲實體  
    transient Entry<K,V>[] table = (Entry<K,V>[]) EMPTY_TABLE;  

    //HashMap的元素數目  
    transient int size;  

    //HashMap下次擴容是的閥值  
    int threshold;  

    //HashMap的裝載因子  
    final float loadFactor;  

    //修改次數  
    transient int modCount;  

    //默認的threshold值  
    static final int ALTERNATIVE_HASHING_THRESHOLD_DEFAULT = Integer.MAX_VALUE;  

    //通過虛擬機配置來修改threshold值  
    private static class Holder {  
        static final int ALTERNATIVE_HASHING_THRESHOLD;  

        static {  
            String altThreshold = java.security.AccessController.doPrivileged(  
                new sun.security.action.GetPropertyAction(  
                    "jdk.map.althashing.threshold"));//讀取配置值  

            int threshold;  
            try {  
                threshold = (null != altThreshold)//修改threshold值  
                        ? Integer.parseInt(altThreshold)  
                        : ALTERNATIVE_HASHING_THRESHOLD_DEFAULT;  


                if (threshold == -1) {  
                    threshold = Integer.MAX_VALUE;  
                }  

                if (threshold < 0) {  
                    throw new IllegalArgumentException("value must be positive integer.");  
                }  
            } catch(IllegalArgumentException failed) {  
                throw new Error("Illegal value for 'jdk.map.althashing.threshold'", failed);  
            }  

            ALTERNATIVE_HASHING_THRESHOLD = threshold;  
        }  
    }  

    //計算Hash值時的key  
    transient int hashSeed = 0;  

    //通過初始容量和狀態因子構造HashMap  
    public HashMap(int initialCapacity, float loadFactor) {  
        if (initialCapacity < 0)//參數有效性檢查  
            throw new IllegalArgumentException("Illegal initial capacity: " +  
                                               initialCapacity);  
        if (initialCapacity > MAXIMUM_CAPACITY)//參數有效性檢查  
            initialCapacity = MAXIMUM_CAPACITY;  
        if (loadFactor <= 0 || Float.isNaN(loadFactor))//參數有效性檢查  
            throw new IllegalArgumentException("Illegal load factor: " +  
                                               loadFactor);  

        this.loadFactor = loadFactor;  
        threshold = initialCapacity;  
        init();//這個實現爲空  
    }  

    //通過擴容因子構造HashMap,容量去默認值,即16  
    public HashMap(int initialCapacity) {  
        this(initialCapacity, DEFAULT_LOAD_FACTOR);  
    }  

    //裝載因子取0.75,容量取16,構造HashMap  
    public HashMap() {  
        this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR);  
    }  

    //通過其他Map來初始化HashMap,容量通過其他Map的size來計算,裝載因子取0.75  
    public HashMap(Map<? extends K, ? extends V> m) {  
        this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1,  
                      DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR);  
        inflateTable(threshold);//初始化HashMap底層的數組結構  
        putAllForCreate(m);//添加m中的元素  
    }  
    //選擇合適的容量值,容量值取大於等於最接近number的2的冪數  
    private static int roundUpToPowerOf2(int number) {  
        int rounded = number >= MAXIMUM_CAPACITY //參數有效性檢查  
                ? MAXIMUM_CAPACITY  
                : (rounded = Integer.highestOneBit(number)) != 0  
                    ? (Integer.bitCount(number) > 1) ? rounded << 1 : rounded  
                    : 1;  

        return rounded;  
    }  

    //初始化HashMap的底層數據結構  
    private void inflateTable(int toSize) {  
        int capacity = roundUpToPowerOf2(toSize);//選取合適的容量值  

        threshold = (int) Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1);//選取合適的threshold(擴容閥值)  
        table = new Entry[capacity];//初始化底層數據結構  
        initHashSeedAsNeeded(capacity);//選擇合適的Hash因子  
    }  


    //目前爲空  
    void init() {  
    }  

    //選擇合適的Hash因子,這裏和虛擬機的配置有關  
    final boolean initHashSeedAsNeeded(int capacity) {  
        boolean currentAltHashing = hashSeed != 0;  
        boolean useAltHashing = sun.misc.VM.isBooted() &&  
                (capacity >= Holder.ALTERNATIVE_HASHING_THRESHOLD);  
        boolean switching = currentAltHashing ^ useAltHashing;  
        if (switching) {  
            hashSeed = useAltHashing  
                ? sun.misc.Hashing.randomHashSeed(this)  
                : 0;  
        }  
        return switching;  
    }  

    //計算key的Hash值,這裏針對String類的Key優化了Hash函數
    final int hash(Object k) {  
        int h = hashSeed;  
        if (0 != h && k instanceof String) {//這裏針對String優化了Hash函數,是否使用新的Hash函數和Hash因子有關  
            return sun.misc.Hashing.stringHash32((String) k);  
        }  

        h ^= k.hashCode();  
        h ^= (h >>> 20) ^ (h >>> 12);  
        return h ^ (h >>> 7) ^ (h >>> 4);  
    }  

    //根據Hash值和Hash表的大小選擇合適的Hash桶  
    static int indexFor(int h, int length) {  
        return h & (length-1);  
    }  

    //返回HashMap的元素個數  
    public int size() {  
        return size;  
    }  

    //判斷是否爲空  
    public boolean isEmpty() {  
        return size == 0;  
    }  

    //獲取key值爲key的元素值  
    public V get(Object key) {  
        if (key == null)//如果Key值爲空,則獲取對應的值,這裏也可以看到,HashMap允許null的key,其內部針對null的key有特殊的邏輯  
            return getForNullKey();  
        Entry<K,V> entry = getEntry(key);//獲取實體  

        return null == entry ? null : entry.getValue();//判斷是否爲空,不爲空,則獲取對應的值  
    }  

    //獲取key爲null的實體  
    private V getForNullKey() {  
        if (size == 0) {//如果元素個數爲0,則直接返回null  
            return null;  
        }  
        //key爲null的元素存儲在table的第0個位置  
        for (Entry<K,V> e = table[0]; e != null; e = e.next) {  
            if (e.key == null)//判斷是否爲null  
                return e.value;//返回其值  
        }  
        return null;  
    }  

    //判斷是否有鍵爲key的元素  
    public boolean containsKey(Object key) {  
        return getEntry(key) != null;//這裏需要遍歷  
    }  

    //獲取鍵值爲key的元素  
    final Entry<K,V> getEntry(Object key) {  
        if (size == 0) {//元素個數爲0  
            return null;//直接返回null  
        }  

        int hash = (key == null) ? 0 : hash(key);//獲取key的Hash值  
        for (Entry<K,V> e = table[indexFor(hash, table.length)];//根據key和表的長度,定位到Hash桶  
             e != null;  
             e = e.next) {//進行遍歷  
            Object k;  
            if (e.hash == hash &&  
                ((k = e.key) == key || (key != null && key.equals(k))))//判斷Hash值和對應的key,合適則返回值  
                return e;  
        }  
        return null;  
    }  

    //添加元素  
    public V put(K key, V value) {  
        if (table == EMPTY_TABLE) {//如果底層表爲空,則初始化  
            inflateTable(threshold);  
        }  
        if (key == null)//如果key爲空,則執行空的邏輯  
            return putForNullKey(value);  
        int hash = hash(key);//獲取key的Hash值  
        int i = indexFor(hash, table.length);//定位Hash桶  
        for (Entry<K,V> e = table[i]; e != null; e = e.next) {  
            Object k;  
            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {  
                V oldValue = e.value;  
                e.value = value;  
                e.recordAccess(this);//調用value的回調函數,其實這個函數也爲空實現  
                return oldValue;  
            }  
        }  

        modCount++;//更新修改次數  
        addEntry(hash, key, value, i);//添加到對應Hash桶的鏈接表中  
        return null;  
    }  

    //添加key爲空的元素,key爲null的元素添加到第0號Hash桶中  
    private V putForNullKey(V value) {  
        for (Entry<K,V> e = table[0]; e != null; e = e.next) {  
            if (e.key == null) {//判斷元素  
                V oldValue = e.value;//如果已經存在,修改值  
                e.value = value;  
                e.recordAccess(this);  
                return oldValue;  
            }  
        }  
        modCount++;//更新修改次數  
        addEntry(0, null, value, 0);//執行鏈表插入  
        return null;  
    }  

    //添加元素  
    private void putForCreate(K key, V value) {  
        int hash = null == key ? 0 : hash(key);//計算key的Hash值  
        int i = indexFor(hash, table.length);//定位Hash桶  

        //遍歷第i號Hash桶  
        for (Entry<K,V> e = table[i]; e != null; e = e.next) {  
            Object k;  
            if (e.hash == hash &&  
                ((k = e.key) == key || (key != null && key.equals(k)))) {  
                e.value = value;  
                return;  
            }  
        }  
        //創建元素實體,這裏會添加到第i號Hash桶中  
        createEntry(hash, key, value, i);  
    }  
    //添加m中的元素到HashMap中  
    private void putAllForCreate(Map<? extends K, ? extends V> m) {  
        for (Map.Entry<? extends K, ? extends V> e : m.entrySet())//遍歷添加  
            putForCreate(e.getKey(), e.getValue());  
    }  

    //按新的容量擴容Hash表  
    void resize(int newCapacity) {  
        Entry[] oldTable = table;//老的數據  
        int oldCapacity = oldTable.length;//獲取老的容量值  
        if (oldCapacity == MAXIMUM_CAPACITY) {//老的容量值已經到了最大容量值  
            threshold = Integer.MAX_VALUE;//修改擴容閥值  
            return;  
        }  
        //新的結構  
        Entry[] newTable = new Entry[newCapacity];  
        transfer(newTable, initHashSeedAsNeeded(newCapacity));//將老的表中的數據拷貝到新的結構中  
        table = newTable;//修改HashMap的底層數組  
        threshold = (int)Math.min(newCapacity * loadFactor, MAXIMUM_CAPACITY + 1);//修改閥值  
    }  

    //將老的表中的數據拷貝到新的結構中  
    void transfer(Entry[] newTable, boolean rehash) {  
        int newCapacity = newTable.length;//容量  
        for (Entry<K,V> e : table) {  
            while(null != e) {  
                Entry<K,V> next = e.next;  
                if (rehash) {//如果是重新Hash,則需要重新計算hash值  
                    e.hash = null == e.key ? 0 : hash(e.key);  
                }  
                int i = indexFor(e.hash, newCapacity);//定位Hash桶  
                e.next = newTable[i];//元素連接到桶中,這裏相當於單鏈表的插入  
                newTable[i] = e;  
                e = next;  
            }  
        }  
    }  

    //添加元素  
    public void putAll(Map<? extends K, ? extends V> m) {  
        int numKeysToBeAdded = m.size();  
        if (numKeysToBeAdded == 0)//m爲空,則直接返回  
            return;  

        if (table == EMPTY_TABLE) {//底層數組爲空  
            inflateTable((int) Math.max(numKeysToBeAdded * loadFactor, threshold));//執行初始化  
        }  

        //按m的size執行HashMap的擴容  
        if (numKeysToBeAdded > threshold) {//閥值代表的擴容的條件,如果比閥值要大,則一定要擴容  
            int targetCapacity = (int)(numKeysToBeAdded / loadFactor + 1);//選擇容量值  
            if (targetCapacity > MAXIMUM_CAPACITY)//有效性判斷  
                targetCapacity = MAXIMUM_CAPACITY;  
            int newCapacity = table.length;//目前的容量  
            while (newCapacity < targetCapacity)//如果小於m的容量,則增加目前的容量  
                newCapacity <<= 1;  
            if (newCapacity > table.length)  
                resize(newCapacity);//執行擴容  
        }  
        //有足夠的空間之後進行擴容  
        for (Map.Entry<? extends K, ? extends V> e : m.entrySet())  
            put(e.getKey(), e.getValue());//執行添加操作  
    }  

    //刪除元素,元素的鍵值爲key  
    public V remove(Object key) {  
        Entry<K,V> e = removeEntryForKey(key);//刪除鍵爲key的元素  
        return (e == null ? null : e.value);//同時返回該值  
    }  

    //刪除元素,元素的鍵值爲key  
    final Entry<K,V> removeEntryForKey(Object key) {  
        if (size == 0) {  
            return null;  
        }  
        int hash = (key == null) ? 0 : hash(key);//計算Hash值  
        int i = indexFor(hash, table.length);//定位Hash桶  
        Entry<K,V> prev = table[i];  
        Entry<K,V> e = prev;//保存前面一個指針值  

        while (e != null) {  
            Entry<K,V> next = e.next;  
            Object k;  
            if (e.hash == hash &&  
                ((k = e.key) == key || (key != null && key.equals(k)))) {//在Hash桶中定位元素  
                modCount++;//更新修改次數  
                size--;//元素個數-1  
                if (prev == e)//是否是第一個元素  
                    table[i] = next;  
                else  
                    prev.next = next;//執行的是單鏈表的刪除  
                e.recordRemoval(this);  
                return e;  
            }  
            prev = e;//單鏈表移動指針  
            e = next;  
        }  

        return e;  
    }  

    //刪除一個Entry實體,這裏通過o的key查找到元素,之後刪除,和上面的實現類似  
    final Entry<K,V> removeMapping(Object o) {  
        if (size == 0 || !(o instanceof Map.Entry))//參數有效性驗證  
            return null;  

        Map.Entry<K,V> entry = (Map.Entry<K,V>) o;  
        Object key = entry.getKey();  
        int hash = (key == null) ? 0 : hash(key);  
        int i = indexFor(hash, table.length);  
        Entry<K,V> prev = table[i];  
        Entry<K,V> e = prev;  

        while (e != null) {  
            Entry<K,V> next = e.next;  
            if (e.hash == hash && e.equals(entry)) {  
                modCount++;  
                size--;  
                if (prev == e)  
                    table[i] = next;  
                else  
                    prev.next = next;  
                e.recordRemoval(this);  
                return e;  
            }  
            prev = e;  
            e = next;  
        }  

        return e;  
    }  

    //清空Hash表  
    public void clear() {  
        modCount++;//更新修改次數  
        Arrays.fill(table, null);//底層數組置爲null  
        size = 0;//元素個數爲0  
    }  

    //判斷是否包含值爲value的元素  
    public boolean containsValue(Object value) {  
        if (value == null)//值爲null  
            return containsNullValue();//執行null的邏輯  

        Entry[] tab = table;  
        //執行兩層循環來查找  
        for (int i = 0; i < tab.length ; i++)  
            for (Entry e = tab[i] ; e != null ; e = e.next)  
                if (value.equals(e.value))//這裏判斷內容  
                    return true;  
        return false;  
    }  

    //執行null的邏輯  
    private boolean containsNullValue() {  
        Entry[] tab = table;  
        for (int i = 0; i < tab.length ; i++)  
            for (Entry e = tab[i] ; e != null ; e = e.next)  
                if (e.value == null)//這裏直接判斷引用  
                    return true;  
        return false;  
    }  

    //淺複製HashMap  
    public Object clone() {  
        HashMap<K,V> result = null;  
        try {  
            result = (HashMap<K,V>)super.clone();  
        } catch (CloneNotSupportedException e) {  
            // assert false;  
        }  
        if (result.table != EMPTY_TABLE) {  
            result.inflateTable(Math.min(  
                (int) Math.min(  
                    size * Math.min(1 / loadFactor, 4.0f),  
                    // we have limits...  
                    HashMap.MAXIMUM_CAPACITY),  
               table.length));  
        }  
        result.entrySet = null;  
        result.modCount = 0;  
        result.size = 0;  
        result.init();  
        result.putAllForCreate(this);  

        return result;  
    }  
    //實現Map.Entry接口,這是HashMap內部key和value的一個抽象  
    static class Entry<K,V> implements Map.Entry<K,V> {  
        final K key;//鍵  
        V value;//值  
        Entry<K,V> next;//指向下一個元素的指針  
        int hash;//key的hash值  

        //創建Entry  
        Entry(int h, K k, V v, Entry<K,V> n) {  
            value = v;  
            next = n;  
            key = k;  
            hash = h;  
        }  

        public final K getKey() {  
            return key;  
        }  

        public final V getValue() {  
            return value;  
        }  

        public final V setValue(V newValue) {  
            V oldValue = value;  
            value = newValue;  
            return oldValue;  
        }  
        //判斷元素內容  
        public final boolean equals(Object o) {  
            if (!(o instanceof Map.Entry))  
                return false;  
            Map.Entry e = (Map.Entry)o;  
            Object k1 = getKey();  
            Object k2 = e.getKey();  
            if (k1 == k2 || (k1 != null && k1.equals(k2))) {//判斷鍵  
                Object v1 = getValue();  
                Object v2 = e.getValue();  
                if (v1 == v2 || (v1 != null && v1.equals(v2)))//判斷值  
                    return true;  
            }  
            return false;  
        }  

        public final int hashCode() {  
            return Objects.hashCode(getKey()) ^ Objects.hashCode(getValue());//鍵和值的hash值的異或  
        }  

        public final String toString() {  
            return getKey() + "=" + getValue();  
        }  

        //空實現  
        void recordAccess(HashMap<K,V> m) {  
        }  

        //空實現  
        void recordRemoval(HashMap<K,V> m) {  
        }  
    }  

    //添加Entry  
    void addEntry(int hash, K key, V value, int bucketIndex) {  
        if ((size >= threshold) && (null != table[bucketIndex])) {//判斷是否需要擴容  
            resize(2 * table.length);//按2倍擴容  
            hash = (null != key) ? hash(key) : 0;//計算hash值  
            bucketIndex = indexFor(hash, table.length);//定位Hash桶  
        }  

        createEntry(hash, key, value, bucketIndex);//創建元素  
    }  

    //創建元素  
    void createEntry(int hash, K key, V value, int bucketIndex) {  
        Entry<K,V> e = table[bucketIndex];  
        table[bucketIndex] = new Entry<>(hash, key, value, e);//這裏執行鏈接操作  
        size++;//元素個數+1  
    }  
    //繼承了Iterator接口,提供迭代器實現  
    private abstract class HashIterator<E> implements Iterator<E> {  
        Entry<K,V> next;        //下一個實體  
        int expectedModCount;   //迭代器修改次數  
        int index;              //Hash桶的索引號  
        Entry<K,V> current;     //當前實體  

        HashIterator() {  
            expectedModCount = modCount;//更新修改次數  
            if (size > 0) { //目前有元素  
                Entry[] t = table;  
                while (index < t.length && (next = t[index++]) == null)//尋找第一個不爲空的Hash桶  
                    ;  
            }  
        }  
        //判斷是否有下一個元素  
        public final boolean hasNext() {  
            return next != null;  
        }  
        //返回下一個元素  
        final Entry<K,V> nextEntry() {  
            if (modCount != expectedModCount)//迭代期間有修改,則拋出異常  
                throw new ConcurrentModificationException();  
            Entry<K,V> e = next;//從next開始遍歷  
            if (e == null)  
                throw new NoSuchElementException();  

            if ((next = e.next) == null) {//如果爲空,則找到下一個不爲空的Hash桶  
                Entry[] t = table;  
                while (index < t.length && (next = t[index++]) == null)  
                    ;  
            }  
            current = e;//返回next的值  
            return e;  
        }  
        //刪除元素  
        public void remove() {  
            if (current == null)  
                throw new IllegalStateException();  
            if (modCount != expectedModCount)  
                throw new ConcurrentModificationException();  
            Object k = current.key;  
            current = null;  
            HashMap.this.removeEntryForKey(k);//調用父類刪除元素  
            expectedModCount = modCount;//修改併發修改次數  
        }  
    }  
    //HashMap值集迭代器,依賴Entry迭代器  
    private final class ValueIterator extends HashIterator<V> {  
        public V next() {  
            return nextEntry().value;  
        }  
    }  
    //HashMap鍵集迭代器,依賴Entry迭代器  
    private final class KeyIterator extends HashIterator<K> {  
        public K next() {  
            return nextEntry().getKey();  
        }  
    }  
    //HashMap Entry迭代器  
    private final class EntryIterator extends HashIterator<Map.Entry<K,V>> {  
        public Map.Entry<K,V> next() {  
            return nextEntry();  
        }  
    }  

    //返回鍵集迭代器  
    Iterator<K> newKeyIterator()   {  
        return new KeyIterator();  
    }  
    //返回值集迭代器  
    Iterator<V> newValueIterator()   {  
        return new ValueIterator();  
    }  
    //返回Entry迭代器      
    Iterator<Map.Entry<K,V>> newEntryIterator()   {  
        return new EntryIterator();  
    }  


    //視圖結合,HashMap內部Entry的集合  
    private transient Set<Map.Entry<K,V>> entrySet = null;  

    //返回鍵集  
    public Set<K> keySet() {  
        Set<K> ks = keySet;  
        return (ks != null ? ks : (keySet = new KeySet()));  
    }  
    //鍵集合的實現,實現了AbstractSet抽象類,調用了父類的方法  
    private final class KeySet extends AbstractSet<K> {  
        public Iterator<K> iterator() {  
            return newKeyIterator();  
        }  
        public int size() {  
            return size;  
        }  
        public boolean contains(Object o) {  
            return containsKey(o);  
        }  
        public boolean remove(Object o) {  
            return HashMap.this.removeEntryForKey(o) != null;  
        }  
        public void clear() {  
            HashMap.this.clear();  
        }  
    }  

    //返回值集合  
    public Collection<V> values() {  
        Collection<V> vs = values;  
        return (vs != null ? vs : (values = new Values()));  
    }  
    //值集合的實現,實現了AbstractCollection抽象類,調用了父類的方法來實現  
    private final class Values extends AbstractCollection<V> {  
        public Iterator<V> iterator() {  
            return newValueIterator();  
        }  
        public int size() {  
            return size;  
        }  
        public boolean contains(Object o) {  
            return containsValue(o);  
        }  
        public void clear() {  
            HashMap.this.clear();  
        }  
    }  

    //entry集合  
    public Set<Map.Entry<K,V>> entrySet() {  
        return entrySet0();  
    }  
    //防火entry集合  
    private Set<Map.Entry<K,V>> entrySet0() {  
        Set<Map.Entry<K,V>> es = entrySet;  
        return es != null ? es : (entrySet = new EntrySet());  
    }  
    //entry集合的實現,繼承了AbstractSet抽象類  
    private final class EntrySet extends AbstractSet<Map.Entry<K,V>> {  
        public Iterator<Map.Entry<K,V>> iterator() {//迭代器的實現  
            return newEntryIterator();  
        }  
        public boolean contains(Object o) {  
            if (!(o instanceof Map.Entry))  
                return false;  
            Map.Entry<K,V> e = (Map.Entry<K,V>) o;  
            Entry<K,V> candidate = getEntry(e.getKey());  
            return candidate != null && candidate.equals(e);  
        }  
        public boolean remove(Object o) {  
            return removeMapping(o) != null;  
        }  
        public int size() {  
            return size;  
        }  
        public void clear() {  
            HashMap.this.clear();  
        }  
    }  
    //序列化和反序列化的實現  
}  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章