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


转载于:https://my.oschina.net/u/140462/blog/190778

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值