HashMap源碼註釋

package java.util;
import java.io.*;

public class HashMap<K,V>
    extends AbstractMap<K,V>
    implements Map<K,V>, Cloneable, Serializable
{

    /**
     * 默認的初始容量,必須是2的冪
     */
    static final int DEFAULT_INITIAL_CAPACITY = 16;

    /**
     * MUST be a power of two <= 1<<30.
     * 最大容量,若是構造方法沒有設置參數將指定一個較高值
     */
    static final int MAXIMUM_CAPACITY = 1 << 30;

    /**
     * 默認裝載因子。
     * 默認的entry數組的長度爲16。裝載因子的意義在於使得entry數組有冗餘,
     * 默認即容許25%的冗餘,當HashMap的數據的個數超過12(16*0.75)時
     * 即會對entry數組進行第一次擴容,後面的再次擴容依次類推。
     */
    static final float DEFAULT_LOAD_FACTOR = 0.75f;

    /**
     * 存儲實體的數組,可調整。數據長度老是2的冪
     * transient 序列化時忽略該字段。數組存放的是實體的引用,序列化時必須遍歷該字段逐個實體序列化。
     */
    transient Entry[] table;

    /**
     * 鍵值對的數目
     * transient 序列化時忽略該字段。反序列化的時候讀取出每對key、value值,再存入HashMap的數組中
     */
    transient int size;

    /**
     * 下一個容量調整值(擴容臨界值)
     */
    int threshold;

    /**
     * 裝載因子
     * @serial
     */
    final float loadFactor;

    /**
     * map結構被改變的次數
     * 結構上的修改是指更改在HashMap中映射的數量或以其餘方式修改它的內部結構(例如,刷新)
     * 該字段在HashMap使用迭代器遍歷的時候使用
     */
    transient volatile int modCount;

    /**
     * 根據初始容量和加載因子建立一個空的HashMap
     * (初始容量小於0或裝載因子小於等於0將報異常)
     */
    public HashMap(int initialCapacity, float loadFactor) {
    	  // 初始容量小於0,拋出非法參數異常
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal initial capacity: " +
                                               initialCapacity);
        // 初始容量大於最大容量,調整初始容量
        if (initialCapacity > MAXIMUM_CAPACITY)
            initialCapacity = MAXIMUM_CAPACITY;
        // 加載因子小於等於0或者非浮點數,拋出非法參數異常
        if (loadFactor <= 0 || Float.isNaN(loadFactor))
            throw new IllegalArgumentException("Illegal load factor: " +
                                               loadFactor);

        // Find a power of 2 >= initialCapacity
        // 設置capacity爲大於initialCapacity且是2的冪的最小值
        int capacity = 1;
        while (capacity < initialCapacity)
            capacity <<= 1;
				
				//設置加載因子
        this.loadFactor = loadFactor;
        //設置擴容臨界值
        threshold = (int)(capacity * loadFactor);
        //建立數組
        table = new Entry[capacity];
        //初始化
        init();
    }

    /**
     * 根據指定容量建立一個空的HashMap
     */
    public HashMap(int initialCapacity) {
    	  // 調用上面的構造方法,容量爲指定的容量,裝載因子是默認值
        this(initialCapacity, DEFAULT_LOAD_FACTOR);
    }

    /**
     * 根據默認初始化容量和默認加載因子(0.75)建立HashMap
     */
    public HashMap() {
        this.loadFactor = DEFAULT_LOAD_FACTOR;
        threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);
        table = new Entry[DEFAULT_INITIAL_CAPACITY];
        init();
    }

    /**
     * 經過傳入的map建立一個HashMap,容量爲默認容量(16)和(map.zise()/DEFAULT_LOAD_FACTORY)+1
     * 的較大者,裝載因子爲默認值
     */
    public HashMap(Map<? extends K, ? extends V> m) {
        this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1,DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR);
        putAllForCreate(m);
    }

    // internal utilities

    /**
     * 初始化方法(鉤子方法)
     * 全部的構造方法和僞構造方法(clone,readObject)將在HashMap初始化完成以後,元素插入以前調用該方法
     */
    void init() {
    }

    /**
     * 適用補充hash函數,防止質量較差的hash函數。
     * 該方法主要做用是防止質量較差的哈希函數帶來過多的衝突(碰撞)問題。
     * Java中int值佔4個字節,即32位。根據這32位值進行移位、異或運算獲得一個值。
     */
    static int hash(int h) {
        h ^= (h >>> 20) ^ (h >>> 12);
        return h ^ (h >>> 7) ^ (h >>> 4);
    }

    /**
     * 返回Hash code h的值在存儲數組中的索引
     * 爲啥和length-1進行與運算,由於這樣能夠保證結果的最大值是length-1,不會產生數組越界問題。
     */
    static int indexFor(int h, int length) {
        return h & (length-1);
    }

    /**
     * 鍵存儲值對的數量
     */
    public int size() {
        return size;
    }

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

    /**
     * 根據key查詢value
     *
     * @see #put(Object, Object)
     */
    public V get(Object key) {
    		//key爲空
        if (key == null)
            return getForNullKey();
        
        //計算key哈希
        int hash = hash(key.hashCode());
        //遍歷鏈表
        for (Entry<K,V> e = table[indexFor(hash, table.length)]; e != null; e = e.next) {
            Object k;
            if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
                return e.value;
        }
        return null;
    }

    /**
     * 查詢key爲null時的值
     */
    private V getForNullKey() {
    		//遍歷索引爲零的鏈表,key爲null時映射的索引位置爲0
        for (Entry<K,V> e = table[0]; e != null; e = e.next) {
            if (e.key == null)
                return e.value;
        }
        return null;
    }

    /**
     * 是否包含key
     */
    public boolean containsKey(Object key) {
        return getEntry(key) != null;
    }

    /**
     * 根據key獲取對應的值,沒有則返回空
     */
    final Entry<K,V> getEntry(Object key) {
    		//計算哈希值
        int hash = (key == null) ? 0 : hash(key.hashCode());
        //遍歷鏈表,查詢對應的值
        for (Entry<K,V> e = table[indexFor(hash, table.length)];
             e != null;
             e = e.next) {
            Object k;
            if (e.hash == hash &&
                ((k = e.key) == key || (key != null && key.equals(k))))
                return e;
        }
        return null;
    }


    /**
     * 將指定的值映射指定的鍵。若是指定的鍵已存在映射關係,則舊值會被替換。
     */
    public V put(K key, V value) {
    		//若是key爲空,則調用putForNullKey方法
        if (key == null)
            return putForNullKey(value);
        //調用補充hash方法(防止低質量hash方法形成衝突過多問題)
        int hash = hash(key.hashCode());
        //獲取hash code對應的存儲數組索引
        int i = indexFor(hash, table.length);
        //遍歷目標存儲數組單元下的鏈表
        for (Entry<K,V> e = table[i]; e != null; e = e.next) {
            Object k;
            //若是已存在鍵值對值的hash等於將要插入兼職對值的hash,而且已存在鍵值對鍵等於將要插入鍵值對鍵
            //(內存地址相等或者equals)
            //即同鍵值覆蓋
            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
                V oldValue = e.value;
                e.value = value;
                e.recordAccess(this);
                //返回舊值
                return oldValue;
            }
        }
				
	//修改記錄Map改變次數的值
        modCount++;
        //添加鍵值對
        addEntry(hash, key, value, i);
        return null;
    }

    /**
     * 空鍵插入(私有方法)
     */
    private V putForNullKey(V value) {
    	  //先遍歷數組,若是存在key爲空的,先替換值並返回舊值
        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;
    }

    /**
     * 該方法被構造函數和僞構造函數(clone,readObject)用來替代put方法。
     * 該方法不擴展數組,不檢查map修改次數,方法體調用createEntry方法而非addEntry
     *
     */
    private void putForCreate(K key, V value) {
        int hash = (key == null) ? 0 : hash(key.hashCode());
        int i = indexFor(hash, table.length);

        /**
         * Look for preexisting entry for key.  This will never happen for
         * clone or deserialize.  It will only happen for construction if the
         * input Map is a sorted map whose ordering is inconsistent w/ equals.
         *
         * 遍歷已存在的鍵,若是和當前key相等,則值替換後返回
         */
        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;
            }
        }
				
	// 沒有則建立
        createEntry(hash, key, value, i);
    }
		
		/**
		 *  將指定map中數據插入到當前map中
		 */
    private void putAllForCreate(Map<? extends K, ? extends V> m) {
        for (Iterator<? extends Map.Entry<? extends K, ? extends V>> i = m.entrySet().iterator(); i.hasNext(); ) {
            Map.Entry<? extends K, ? extends V> e = i.next();
            putForCreate(e.getKey(), e.getValue());
        }
    }

    /**
     * 將當前數據複製到容量更大的數組中。
     * 該方法在存儲數量達到臨界值時自動被調用
     *
     * 若是當前容量已達到最大值,該方法不在調整map容量大小,但會設置擴容臨界值爲Integer.MAX_VALUE。
     * 這具備防止未來調用的效果
     */
    void resize(int newCapacity) {
    		// 若是舊數組到達最大值,設置擴容臨界值爲Integer.MAX_VALUE
        Entry[] oldTable = table;
        int oldCapacity = oldTable.length;
        if (oldCapacity == MAXIMUM_CAPACITY) {
            threshold = Integer.MAX_VALUE;
            return;
        }
				
				//建立指定容量的新數組存儲舊數據
        Entry[] newTable = new Entry[newCapacity];
        transfer(newTable);
        table = newTable;
        //從新設置擴容臨界值
        threshold = (int)(newCapacity * loadFactor);
    }

    /**
     * Transfers all entries from current table to newTable.
     * 將全部數據從當前數組複製到新數組
     *
     * HashMap之因此不能保持元素的順序有如下幾點緣由:
     * 第一,插入元素的時候對元素進行哈希處理,不一樣元素分配到table的不一樣位置;
     * 第二,容量拓展的時候又進行了hash處理;
     * 第三,複製原表內容的時候鏈表被倒置。
     */
    void transfer(Entry[] newTable) {
    	  //保留原數組引用
        Entry[] src = table;
        //新的容量
        int newCapacity = newTable.length;
        //遍歷源數組
        for (int j = 0; j < src.length; j++) {
        		//獲取元素e
            Entry<K,V> e = src[j];
            if (e != null) {
            		// 將原數組中的元素置爲null
                src[j] = null;
                do {
                		//循環鏈表
                    Entry<K,V> next = e.next;
                    // 根據新的容量計算e在新數組中的索引
                    int i = indexFor(e.hash, newCapacity);
                    // 將e插入到newTable[i]指向的鏈表的頭部
                    e.next = newTable[i];
                    newTable[i] = e;
                    e = next;
                } while (e != null);
            }
        }
    }

    /**
     *
     * 複製全部指定map的映射到當前的map。
     * 重複的映射會被替換。(即當前map中的key和指定參數map的key相同,值會被替換)
     */
    public void putAll(Map<? extends K, ? extends V> m) {
        int numKeysToBeAdded = m.size();
        if (numKeysToBeAdded == 0)
            return;

        /*
         *  爲何判斷條件是numKeysToBeAdded,
         *  不是(numKeysToBeAdded+table.length)>threshold?
         *
         *  這是一種保守的作法,明顯地,咱們應該在(numKeysToBeAdded+table.length)>threshold
         *  的時候去拓展容量,可是考慮到將被添加的元素可能會有Key與本來存在的Key相同的狀況,
         *  因此採用保守的作法,避免拓展到過大的容量。
         */
        if (numKeysToBeAdded > threshold) {
        		//計算目標容量
            int targetCapacity = (int)(numKeysToBeAdded / loadFactor + 1);
            //目標容量超過最大值, targetCapacity = MAXIMUM_CAPACITY;
            if (targetCapacity > MAXIMUM_CAPACITY)
                targetCapacity = MAXIMUM_CAPACITY;  
            //獲取大於目標容量最小的2的冥,這就是信容量
            int newCapacity = table.length;
            while (newCapacity < targetCapacity)
                newCapacity <<= 1;
            //新容量大於當前數組長度,則擴容
            if (newCapacity > table.length)
                resize(newCapacity);
        }
				
				//遍歷m中的數據,插入到當前的map中
        for (Iterator<? extends Map.Entry<? extends K, ? extends V>> i = m.entrySet().iterator(); i.hasNext(); ) {
            Map.Entry<? extends K, ? extends V> e = i.next();
            put(e.getKey(), e.getValue());
        }
    }

    /**
     *
     * 根據key刪除鍵值對
     */
    public V remove(Object key) {
        Entry<K,V> e = removeEntryForKey(key);
        return (e == null ? null : e.value);
    }

    /**
     * 根據key刪除鍵值對
     */
    final Entry<K,V> removeEntryForKey(Object key) {
    		//計算key哈希
        int hash = (key == null) ? 0 : hash(key.hashCode());
        //計算數組索引
        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;
            Object k;
            if (e.hash == hash &&
                ((k = e.key) == key || (key != null && key.equals(k)))) {
                modCount++;
                size--;
                if (prev == e)
                    table[i] = next;
                else
                    prev.next = next;
                e.recordRemoval(this);
                return e;
            }
            prev = e;
            e = next;
        }

        return e;
    }

    /**
     * Special version of remove for EntrySet.
     */
    final Entry<K,V> removeMapping(Object o) {
        if (!(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.hashCode());
        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;
    }

    /**
     *
     * 清空map
     */
    public void clear() {
        modCount++;
        Entry[] tab = table;
        //清空數組
        for (int i = 0; i < tab.length; i++)
            tab[i] = null;
        size = 0;
    }

    /**
     *
     * 是否包含指定值
     *
     */
    public boolean containsValue(Object value) {
    	 //value爲空
			 if (value == null)
		            return containsNullValue();
			 
			 //遍歷數組和鏈表(雙重循環,較耗時)
			 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的value
     */
    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;
    }

    /**
     * Returns a shallow copy of this <tt>HashMap</tt> instance: the keys and
     * values themselves are not cloned.
     *
     * 克隆(只複製引用) 
     * 
     */
    public Object clone() {
        HashMap<K,V> result = null;
				try {
						//建立一個空的Map
				    result = (HashMap<K,V>)super.clone();
				} catch (CloneNotSupportedException e) {
				    // assert false;
				}
        result.table = new Entry[table.length];
        result.entrySet = null;
        result.modCount = 0;
        result.size = 0;
        result.init();
        //將當前的鍵值對插入到新的Map
        result.putAllForCreate(this);

        return result;
    }

    static class Entry<K,V> implements Map.Entry<K,V> {
        final K key;
        V value;
        //對下一個節點的引用
        Entry<K,V> next;
        final int hash;

        /**
         * Creates new 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;
            //返回是舊的Value
            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();
            // Key相等且Value相等則兩個Entry相等
            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;
        }
				
				// hashCode是Key的hashCode和Value的hashCode的異或的結果
        public final int hashCode() {
            return (key==null   ? 0 : key.hashCode()) ^
                   (value==null ? 0 : value.hashCode());
        }
				
				// 覆寫toString方法,方便調試和查看輸出
        public final String toString() {
            return getKey() + "=" + getValue();
        }

        /**
         * 當調用put(k,v)方法存入鍵值對時,若是k已經存在,則該方法被調用。
         * (沒有函數體、default做用域,why?)
         */
        void recordAccess(HashMap<K,V> m) {
        }

        /**
         * 當Entry被從HashMap中移除時被調用。
         * (沒有函數體、default做用域,why?)
         */
        void recordRemoval(HashMap<K,V> m) {
        }
    }

    /**
     *
     * 根據指定的鍵,值和哈希碼添加新條目到指定的容器
     * 
     */
    void addEntry(int hash, K key, V value, int bucketIndex) {
    		//獲取鏈表頭結點
				Entry<K,V> e = table[bucketIndex];
				//在鏈表頭插入新節點,next指向原來的頭結點
        table[bucketIndex] = new Entry<K,V>(hash, key, value, e);
        //若是size達到擴容臨界值,則擴容
        if (size++ >= threshold)
            resize(2 * table.length);
    }

    /**
     * Like addEntry except that this version is used when creating entries
     * as part of Map construction or "pseudo-construction" (cloning,
     * deserialization).  This version needn't worry about resizing the table.
     *
     * Subclass overrides this to alter the behavior of HashMap(Map),
     * clone, and readObject.
     */
    void createEntry(int hash, K key, V value, int bucketIndex) {
				Entry<K,V> e = table[bucketIndex];
        table[bucketIndex] = new Entry<K,V>(hash, key, value, e);
        size++;
    }

    private abstract class HashIterator<E> implements Iterator<E> {
        Entry<K,V> next;	// next entry to return
        int expectedModCount;	// For fast-fail
        int index;		// current slot
        Entry<K,V> current;	// current entry

        HashIterator() {
            expectedModCount = modCount;
            if (size > 0) { // advance to first entry
            		//設置next指向數組第一項
                Entry[] t = table;
                while (index < t.length && (next = t[index++]) == null)
                    ;
            }
        }

        public final boolean hasNext() {
            return next != null;
        }

        final Entry<K,V> nextEntry() {
        		//迭代過程當中map被修改,拋出異常
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
           	//獲取下一項引用
            Entry<K,V> e = next;
            //爲空,拋出異常
            if (e == null)
                throw new NoSuchElementException();
						
						//(next引用指向下一項的下一項)若是下一項爲鏈表的最後一項,則執行if裏面代碼(next指向數組的下一個非空索引)
            if ((next = e.next) == null) {
                Entry[] t = table;
                while (index < t.length && (next = t[index++]) == null)
                    ;
            }
            //將當前應用執行下一項,並返回
	    			current = e;
            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;
        }

    }

    private final class ValueIterator extends HashIterator<V> {
        public V next() {
            return nextEntry().value;
        }
    }

    private final class KeyIterator extends HashIterator<K> {
        public K next() {
            return nextEntry().getKey();
        }
    }

    private final class EntryIterator extends HashIterator<Map.Entry<K,V>> {
        public Map.Entry<K,V> next() {
            return nextEntry();
        }
    }

    // Subclass overrides these to alter behavior of views' iterator() method
    Iterator<K> newKeyIterator()   {
        return new KeyIterator();
    }
    Iterator<V> newValueIterator()   {
        return new ValueIterator();
    }
    Iterator<Map.Entry<K,V>> newEntryIterator()   {
        return new EntryIterator();
    }


    // Views

    private transient Set<Map.Entry<K,V>> entrySet = null;

    /**
     * Returns a {@link Set} view of the keys contained in this map.
     * The set is backed by the map, so changes to the map are
     * reflected in the set, and vice-versa.  If the map is modified
     * while an iteration over the set is in progress (except through
     * the iterator's own <tt>remove</tt> operation), the results of
     * the iteration are undefined.  The set supports element removal,
     * which removes the corresponding mapping from the map, via the
     * <tt>Iterator.remove</tt>, <tt>Set.remove</tt>,
     * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt>
     * operations.  It does not support the <tt>add</tt> or <tt>addAll</tt>
     * operations.
     */
    public Set<K> keySet() {
        Set<K> ks = keySet;
        return (ks != null ? ks : (keySet = new KeySet()));
    }

    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();
        }
    }

    /**
     * Returns a {@link Collection} view of the values contained in this map.
     * The collection is backed by the map, so changes to the map are
     * reflected in the collection, and vice-versa.  If the map is
     * modified while an iteration over the collection is in progress
     * (except through the iterator's own <tt>remove</tt> operation),
     * the results of the iteration are undefined.  The collection
     * supports element removal, which removes the corresponding
     * mapping from the map, via the <tt>Iterator.remove</tt>,
     * <tt>Collection.remove</tt>, <tt>removeAll</tt>,
     * <tt>retainAll</tt> and <tt>clear</tt> operations.  It does not
     * support the <tt>add</tt> or <tt>addAll</tt> operations.
     */
    public Collection<V> values() {
        Collection<V> vs = values;
        return (vs != null ? vs : (values = new Values()));
    }

    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();
        }
    }

    /**
     *
     * 獲取鍵值對value集合
     *
     * @return a set view of the mappings contained in this map
     */
    public Set<Map.Entry<K,V>> entrySet() {
				return entrySet0();
    }
		
		/**
		 *	獲取鍵值對value集合(得到一個代理類)
		 */
    private Set<Map.Entry<K,V>> entrySet0() {
        Set<Map.Entry<K,V>> es = entrySet;
        return es != null ? es : (entrySet = new EntrySet());
    }
		
		/**
		 * 代理類(沒有定義本身的數據,經過迭代器直接遍歷map中的數組鏈表)
		 */
    private final class EntrySet extends AbstractSet<Map.Entry<K,V>> {
        public Iterator<Map.Entry<K,V>> iterator() {
        		//該代理經過迭代器遍歷map數據,自己不存儲數據
            return newEntryIterator();
        }
        public boolean contains(Object o) {
            if (!(o instanceof Map.Entry))
                return false;
            Map.Entry<K,V> e = (Map.Entry<K,V>) o;
            //調用外部類的getEntry方法
            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();
        }
    }

    /**
     * Save the state of the <tt>HashMap</tt> instance to a stream (i.e.,
     * serialize it).
     *
     * @serialData The <i>capacity</i> of the HashMap (the length of the
     *		   bucket array) is emitted (int), followed by the
     *		   <i>size</i> (an int, the number of key-value
     *		   mappings), followed by the key (Object) and value (Object)
     *		   for each key-value mapping.  The key-value mappings are
     *		   emitted in no particular order.
     */
    private void writeObject(java.io.ObjectOutputStream s)
        throws IOException
    {
				Iterator<Map.Entry<K,V>> i = (size > 0) ? entrySet0().iterator() : null;
			
				//調用默認的序列化流(序列化threshold, loadfactor等私有變量)
				s.defaultWriteObject();
			
				// 序列化數組長度
				s.writeInt(table.length);
			
				// 序列化鍵值對數
				s.writeInt(size);

        // 序列化鍵值對值(非引用)
				if (i != null) {
				    while (i.hasNext()) {
							Map.Entry<K,V> e = i.next();
							s.writeObject(e.getKey());
							s.writeObject(e.getValue());
				    }
			  }
    }

    private static final long serialVersionUID = 362498820763181265L;

    /**
     * 反序列化
     */
    private void readObject(java.io.ObjectInputStream s)
         throws IOException, ClassNotFoundException
    {
			// 根據私有成員建立HashMap
			s.defaultReadObject();

		 	//根據數組長度初始化數組
			 int numBuckets = s.readInt();
			 table = new Entry[numBuckets];
			
			 //鉤子方法(子類若是要在初始化以前處理某些業務,可覆寫該方法)
	     init();  // Give subclass a chance to do its thing.
	
			 //讀取要存儲鍵值對的數量
		   int size = s.readInt();

			// 根據鍵值對數量從流中循環讀取並創建鍵值對
			for (int i=0; i<size; i++) {
			    K key = (K) s.readObject();
			    V value = (V) s.readObject();
			    putForCreate(key, value);
			}
    }

    // These methods are used when serializing HashSets
    int   capacity()     { return table.length; }
    float loadFactor()   { return loadFactor;   }
}
相關文章
相關標籤/搜索