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();  
        }  
    }  
    //序列化和反序列化的实现  
}  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值