一个学生对HashMap源码注释分析

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

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

    /**
     * 默认的数组大小,也就是桶数,必须是2次幂,在indexFor方法会降到2次幂的原因
     */
    static final int DEFAULT_INITIAL_CAPACITY = 16;

    /**
     * 最大的容量,这里1经过左移运算后是个非常大的值
     */
    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的n次幂
     */
    transient Entry[] table;

    /**
     * 键值对的数目
     */
    transient int size;

    /**
     * 阀值,也叫下一个容量的扩充值,最大可使用数组大小
     */
    int threshold;

    /**
     * 装载因子(构造函数可以指定)
     */
    final float loadFactor;

    /**
     * map结构被改变的次数
     * 结构上的修改是指更改在HashMap中映射的数量或以其他方式修改它的内部结构(例如,刷新)
     * 该字段在HashMap使用迭代器遍历的时候判断是否被修改过
     */
    transient int modCount;

    /**
     * 这就是构造函数,参数可以指定桶数组的容量和加载因子,如果初始容量不符合是2次幂的规则,会对它有所调整。
     */
    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);

        // 寻找一个2的k次幂capacity恰好大于initialCapacity的最小值
        int capacity = 1;
        while (capacity < initialCapacity)
            capacity <<= 1;

        this.loadFactor = loadFactor;
        threshold = (int)(capacity * loadFactor);

        table = new Entry[capacity];
        init();
    }

    /**
     * 如果只指定容量,那么就是用默认的加载因子
     */
    public HashMap(int initialCapacity) {
        this(initialCapacity, DEFAULT_LOAD_FACTOR);
    }

    /**
     * 都不指定,那么什么都是默认的
     */
    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);
		//把Map类型的参数m里面的内容放进去
        putAllForCreate(m);
    }

    /**
     * 初始化
     */
    void init() {
    }

    /**
	 * 这是HashMap里面的hash方法,一般是一个Entry里面的key这个对象属性使用
     * 适用补充hash函数,防止质量较差的hash函数。
     * 该方法主要作用是防止质量较差的哈希函数带来过多的冲突(碰撞)问题。
     * Java中int值占4个字节,即32位。根据这32位值进行移位、异或运算得到一个值。
	 * 它的参数是int
     */
    static int hash(int h) {
        h ^= (h >>> 20) ^ (h >>> 12);
        return h ^ (h >>> 7) ^ (h >>> 4);
    }

    /**参数为提供的一个hash值和桶这个数组的长度求取Entry在数组的位置
     * 由于length是2的n次幂,所以h & (length-1)相当于h % length。 
     * 对于length,其2进制表示为1000...0,那么length-1为0111...1(其余都是1)。 
     * 那么对于任何小于length的数h,该式结果都是其本身h。 
     * 对于h = length,该式结果等于0。 
     * 对于大于length的数h,则和0111...1位与运算后,只有对应位置为1时,结果的对应位置才有1	 
     * 相当于减去j个length,该式结果是h-j*length, 
     * 所以相当于h % length。  
	 * 保证结果的最大值为length-1(索引)
     * 这也是为什么length只能是2的n次幂的原因
     */
    static int indexFor(int h, int length) {
        return h & (length-1);
    }

    /**
     * 返回当前键值对数<=当前容量*装载因子
     */
    public int size() {
        return size;
    }

    /**
     * 判断数组里面的是否有键值对
     */
    public boolean isEmpty() {
        return size == 0;
    }

    /**
     * 返回制定键的值,如果没有就返回null
     */
    public V get(Object key) {
        if (key == null)
            return getForNullKey();
		//对key对象的hashcode再次求得hash值,只有用key的hashCode求索引
        int hash = hash(key.hashCode());
		//遍历桶,直到指向hash值对应的桶(也就是遍历链表),从最开始利用hash得到的索引位置开始横向遍历(因为有可能hash相同,值不同)
        for (Entry<K,V> e = table[indexFor(hash, table.length)];
             e != null;
             e = e.next) {
            Object k;
			//如果Entry的hash值与当前hash值相同并且key也相同(因为Entry的hash值就是key对象的hashCode求出来的,在插入Entry的之后求得)
            if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
				//返回这个桶键对应的值
                return e.value;
        }
		//没有找到
        return null;
    }

    /**
     * 如果Key为空,就用这个方法返回对应的值,key为空,那么就从索引为0的位置遍历链表
     */
    private V getForNullKey() {
        for (Entry<K,V> e = table[0]; e != null; e = e.next) {
            if (e.key == null)
                return e.value;
        }
        return null;
    }

    /**
     * 判断给定一个键是否返回一个映射的判断
     */
    public boolean containsKey(Object key) {
        return getEntry(key) != null;
    }

    /**
     * 通过key返回对应的Entry
     */
    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))))//hash值相同,带式key的内容不相同,因为HashMap的对象是不重复的。
                return e;
        }
        return null;
    }


    /**
     * 在此映射表中关联指定值与指定键。如果该映射以前包含了一个该键的映射关系,则旧值被替换,返回旧值,	//如果没有就添加一个新的Entry
     */
    public V put(K key, V value) {
        if (key == null)
            return putForNullKey(value);//吧key等于null的value替换
		
        int hash = hash(key.hashCode());
        int i = indexFor(hash, table.length);
        for (Entry<K,V> e = table[i]; e != null; e = e.next) {//在链表中寻找存在的key
            Object k;
            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
                V oldValue = e.value;
                e.value = value;
                e.recordAccess(this);
                return oldValue;
            }
        }

        modCount++;
		//如果没有就添加一个新的Entry
        addEntry(hash, key, value, i);
        return null;
    }

    /**
     * 当key为null是放进table[0]中去,有可能冲突
     */
    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++;
		//如果table[0]这个桶还是空的话,那么就不用解决冲突
        addEntry(0, null, value, 0);
        return null;
    }

    /**
     * 如果插进一个新的视图,或者节点,这个方法有判断是否需要创建新的桶的必要,也就是键值对数加1
     */
    private void putForCreate(K key, V value) {
		//规定hash值为key来求得,如果为空就是在0下标处,不然从新用hashCode求得
        int hash = (key == null) ? 0 : hash(key.hashCode());
        int i = indexFor(hash, table.length);

        /**
         * 遍历这个下标开始的链表,如果存在相同的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();
			//分别在参数的map里面遍历的每一个视图,都调用上一个方法
            putForCreate(e.getKey(), e.getValue());
        }
    }

    /**
     * 扩容,有参数(addEntry中是两倍当前数组大小)
     *
     */
    void resize(int newCapacity) {
		//这是旧的HasMap
        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);
    }

    /**
     * 将所有数据从当前数组复制到新数组
     */
    void transfer(Entry[] newTable) {
		//旧数组
        Entry[] src = table;
		//新数组长度
        int newCapacity = newTable.length;
		//遍历原来每一个桶
        for (int j = 0; j < src.length; j++) {
            Entry<K,V> e = src[j];
            if (e != null) {
                src[j] = null;
				//遍历每一个桶的链表了,遍历到最后一个桶为空就遍历下个一桶
                do {
					//当前节点的下一个节点
                    Entry<K,V> next = e.next;
					//根据新尺寸求出新的hash值
                    int i = indexFor(e.hash, newCapacity);
					//e插入到当前桶的头结点
                    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;

		//新数组长度比阀值大
        if (numKeysToBeAdded > threshold) {
			//计算新的数组大小
            int targetCapacity = (int)(numKeysToBeAdded / loadFactor + 1);
            if (targetCapacity > MAXIMUM_CAPACITY)
                targetCapacity = MAXIMUM_CAPACITY;
			//获得即比targetCapacity大,也是最小值的2的幂,这就是目标数组的新容量
            int newCapacity = table.length;
            while (newCapacity < targetCapacity)
                newCapacity <<= 1;
			
            if (newCapacity > table.length)
                resize(newCapacity);
        }

		//迭代将key-value映射放进目标HashMap  ,在put里面要么替换旧值,要么使用addEntry添加新视图(在自身数组下)
        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());
        }
    }

    /**
     * 删除已经存在的键值对,要返回删除视图的值,没有就返回空
     */
    public V remove(Object key) {
        Entry<K,V> e = removeEntryForKey(key);
        return (e == null ? null : e.value);
    }

    /**
     * 具体的删除方法,根据键值删除键值对
     * 
     */
    final Entry<K,V> removeEntryForKey(Object key) {
        int hash = (key == null) ? 0 : hash(key.hashCode());
		//如果hash为0,根据与运算,下标为0
        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--;
				//如果要删除第一个节点,那么就把第二个节点当做table[i]也就是table[0]
                if (prev == e)
                    table[i] = next;
                else
					//其他情况就是简单的指针
                    prev.next = next;
                e.recordRemoval(this);
                return e;
            }
			//这两个指针都一项下一项,以便下次操作
            prev = e;
            e = next;
        }

        return e;
    }

    /**
     * 上面那个方法是根据key对象,这里还根据键值对删除
     */
    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;
    }

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

    /**
     * 只根据值查找是否存在,遍历整个map
     * 
     */
    public boolean containsValue(Object 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;
    }

    /**
     * 是否包含空值
     */
    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;
        }
        result.table = new Entry[table.length];
        result.entrySet = null;
        result.modCount = 0;
        result.size = 0;
        result.init();
        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;

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

		//和对象o比较是否相同
        public final boolean equals(Object o) {
			//如果对象o不是Map.Enter类型的话,那就肯定不相同了
            if (!(o instanceof Map.Entry))
                return false;
            Map.Entry e = (Map.Entry)o;
			//当前的Entry的KEY
            Object k1 = getKey();
			//相比较的Entry的KEY
            Object k2 = e.getKey();
			//只有key和value相同的这个两个桶才相等
            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() {
			//这个对象的hashCode = key的hashCode与value的hashCode的异或结果,例如1011和1111的异或结果为0100(只有在相应位置上一个为1一个为0,结果相应位置才为1)
            return (key==null   ? 0 : key.hashCode()) ^
                   (value==null ? 0 : value.hashCode());
        }

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

        /**
         * 使用该方法证明该key已经在该map中,在linkedHashMao实现
         */
        void recordAccess(HashMap<K,V> m) {
        }

        /**
         * 该方法记录该key已经被移除了,在linkedHashMao实现
         */
        void recordRemoval(HashMap<K,V> m) {
        }
    }

    /**
     * 添加一个新桶,bucketIndex为先hash = hash(key.hashCode())然后bucketIndex = indexFor(hash, table.length)求出来这个桶在数组当中的索引
        
     */
    void addEntry(int hash, K key, V value, int bucketIndex) {
        Entry<K,V> e = table[bucketIndex];
        table[bucketIndex] = new Entry<K,V>(hash, key, value, e);
		//扩容
        if (size++ >= threshold)
            resize(2 * table.length);
    }

    /**
     * 同上,只是这个方法不需要判断是否超过阀值
     * 
     */
    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;        // 下一个节点
        int expectedModCount;   // 保护HashMap没有变更
        int index;              // 当前的节点的索引
        Entry<K,V> current;     // 当前的节点

        HashIterator() {
			 // 保存modCount,因为如果HashMap进行了任何操作modCount都会增加,所以如果发现modCount变化了,就可以抛出失败
            expectedModCount = modCount;
			
            if (size > 0) { // 把next指向index位置上的数组的第一项
                Entry[] t = table;
                while (index < t.length && (next = t[index++]) == null)
                    ;
            }
        }

		//下一个节点是否为空
        public final boolean hasNext() {
            return next != null;
        }

		//返回当前节点,相应的指针会有所移动
        final Entry<K,V> nextEntry() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
			//e最开始也指向第一个节点
            Entry<K,V> e = next;
            if (e == null)
                throw new NoSuchElementException();

			//这是遍历的关键,他会从最开始的索引位置向下遍历,while语句的作用是如果这个索引位置上的链表遍历完了的话,就进入下一行,
			//也就是index++,每一次调用e为当前节点,next为下一个节点,next先移动,e后移动,并返回e。
			
            if ((next = e.next) == null) {
                Entry[] t = table;
                while (index < t.length && (next = t[index++]) == null)
                    ;
            }
            current = e;
            return e;
        }

		//删除才经过的节点,也就是此时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;
        }

    }

	//内部的value的迭代器,调用上面的nextEntry()后再取相应的值
    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();
        }
    }

    // 这里的三个Iterator方法返回相应的Iterator对象
    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;

    /**
     * 返回此映射中所包含的键的 Set 视图(Set就像数学的集合一样,不重复是他的特点)。 
     * 该 set 受映射的支持,所以对映射的更改将反映在该 set 中, 
     * 反之亦然。如果在对 set 进行迭代的同时修改了映射(通过迭代器自己的 remove 操作除外), 
     * 则迭代结果是不确定的。该 set 支持元素的移除,通过  
     * Iterator.remove、Set.remove、removeAll、retainAll 和 clear 操作 
     * 可从该映射中移除相应的映射关系。它不支持 add 或 addAll 操作。
     */
    public Set<K> keySet() {
        Set<K> ks = keySet;
		//构造一个Set集合,如果他是空的,说明他还没有实例化,需要相应的new一个
        return (ks != null ? ks : (keySet = new KeySet()));
    }

	//内部类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();
        }
    }

    /**
     * 返回此映射所包含的值的 Collection 视图。 
     * 该 collection 受映射的支持,所以对映射的更改将反映在该 collection 中, 
     * 反之亦然。如果在对 collection 进行迭代的同时修改了映射(通过迭代器自己的 remove 操作除外), 
     * 则迭代结果是不确定的。该 collection 支持元素的移除, 
     * 通过 Iterator.remove、Collection.remove、removeAll、retainAll 和 clear 操作 
     * 可从该映射中移除相应的映射关系。它不支持 add 或 addAll 操作。 
     */
    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();
        }
    }

    /**
     * 返回此映射(HsahMap)所包含的映射关系的 Set 视图。  
     * 该 set 受映射支持,所以对映射的更改将反映在此 set 中, 
     * 反之亦然。如果在对 set 进行迭代的同时修改了映射 
     * (通过迭代器自己的 remove 操作,或者通过在该迭代器返回的映射项上执行 setValue 操作除外), 
     * 则迭代结果是不确定的。该 set 支持元素的移除, 
     * 通过 Iterator.remove、Set.remove、removeAll、retainAll 和 clear 操作 
     * 可从该映射中移除相应的映射关系。它不支持 add 或 addAll 操作。
     */
    public Set<Map.Entry<K,V>> entrySet() {
        return entrySet0();
    }

    private Set<Map.Entry<K,V>> entrySet0() {
        Set<Map.Entry<K,V>> es = entrySet;
        return es != null ? es : (entrySet = new EntrySet());
    }

    private final class EntrySet extends AbstractSet<Map.Entry<K,V>> {
        public Iterator<Map.Entry<K,V>> iterator() {
            return newEntryIterator();
        }
        public boolean contains(Object o) {
			//如果参数提供的对象o不是Map.Entry的话会报错
            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();
        }
    }

    /**
     * 
     */
    private void writeObject(java.io.ObjectOutputStream s)
        throws IOException
    {
        Iterator<Map.Entry<K,V>> i =
            (size > 0) ? entrySet0().iterator() : null;

        // Write out the threshold, loadfactor, and any hidden stuff
        s.defaultWriteObject();

        // Write out number of buckets
        s.writeInt(table.length);

        // Write out size (number of Mappings)
        s.writeInt(size);

        // Write out keys and values (alternating)
        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;

    /**
     * Reconstitute the <tt>HashMap</tt> instance from a stream (i.e.,
     * deserialize it).
     */
    private void readObject(java.io.ObjectInputStream s)
         throws IOException, ClassNotFoundException
    {
        // Read in the threshold, loadfactor, and any hidden stuff
        s.defaultReadObject();

        // Read in number of buckets and allocate the bucket array;
        int numBuckets = s.readInt();
        table = new Entry[numBuckets];

        init();  // Give subclass a chance to do its thing.

        // Read in size (number of Mappings)
        int size = s.readInt();

        // Read the keys and values, and put the mappings in the HashMap
        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;   }
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值