关闭

WeakHashMap 源代码

标签: javaWeakHashMap源代码
294人阅读 评论(0) 收藏 举报
分类:

1、简介

WeakHashMap 以弱引用键实现的基于哈希表的 Map。在 WeakHashMap 中,当某个键不再正常使用时,将自动移除其条目。更精确地说,对于一个给定的键,其映射的存在并不阻止垃圾回收器对该键的丢弃,这就使该键成为可终止的,被终止,然后被回收。丢弃某个键时,其条目从映射中有效地移除。


2、参数介绍

初始化容量

    /**
     * The default initial capacity -- MUST be a power of two.
     */
    //默认的初始化容量为16
    private static final int DEFAULT_INITIAL_CAPACITY = 16;

最大容量

    /**
     * The maximum capacity, used if a higher value is implicitly specified
     * by either of the constructors with arguments.
     * MUST be a power of two <= 1<<30.
     */
    //最大容量为 2^30
    private static final int MAXIMUM_CAPACITY = 1 << 30;

默认加载因子

    /**
     * The load factor used when none specified in constructor.
     */
    //默认的加载因子为0.75f
    private static final float DEFAULT_LOAD_FACTOR = 0.75f;


3、机制

初始化机制:

初始化的容量一定是2的n次方,通过以下代码while循环中,一直左移,直到初始化容量大于传进来的initialCapacity。初始化容量为2^n,且满足2^(n-1) < initialCapacity <= 2^n

        int capacity = 1;
        //循环左移,使初始化容量大于initialCapacity,且为2的n次方
        while (capacity < initialCapacity)
            capacity <<= 1;
        //初始化桶数组
        table = newTable(capacity);
        //赋值加载因子
        this.loadFactor = loadFactor;
        //计算扩容阀值
        threshold = (int)(capacity * loadFactor);

扩容机制:

传入newCapacity为新的要扩容的大小,newCapacity为oldCapacity的2倍,扩容的是桶的个数

扩容的时机是当插入键值对后,键值对数量size>threadhold时,才扩容为原来的2倍,threadhold的计算为threadhold(阀值) = capacity(容量) * loadFactor(加载因子)

    /**
     * Rehashes the contents of this map into a new array with a
     * larger capacity.  This method is called automatically when the
     * number of keys in this map reaches its threshold.
     *
     * If current capacity is MAXIMUM_CAPACITY, this method does not
     * resize the map, but sets threshold to Integer.MAX_VALUE.
     * This has the effect of preventing future calls.
     *
     * @param newCapacity the new capacity, MUST be a power of two;
     *        must be greater than current capacity unless current
     *        capacity is MAXIMUM_CAPACITY (in which case value
     *        is irrelevant).
     */
    //扩容
    void resize(int newCapacity) {
        //获取旧的桶table
        Entry<K,V>[] oldTable = getTable();
        //记录旧的桶的容量
        int oldCapacity = oldTable.length;
        if (oldCapacity == MAXIMUM_CAPACITY) {
            //当旧容量已经是最大容量时,将阀值设为Integer.MAX_VALUE
            threshold = Integer.MAX_VALUE;
            return;
        }

        //创建新的桶table
        Entry<K,V>[] newTable = newTable(newCapacity);
        //将旧的桶中的键值对赋到新的桶
        transfer(oldTable, newTable);
        table = newTable;

        /*
         * If ignoring null elements and processing ref queue caused massive
         * shrinkage, then restore old table.  This should be rare, but avoids
         * unbounded expansion of garbage-filled tables.
         */
        if (size >= threshold / 2) {
            //如果原来的键值对数量已经超过阀值的1/2,则重新设置阀值
            threshold = (int)(newCapacity * loadFactor);
        } else {
            //键值对没有超过阀值的1/2,则将table设置为oldTable
            //这种情况出现几率很小,可能是queue中回收对象太多导致
            expungeStaleEntries();
            transfer(newTable, oldTable);
            table = oldTable;
        }
    }

4、底层实现

底层是通过哈希链表来实现的,单链表。

    /**
     * The table, resized as necessary. Length MUST Always be a power of two.
     */
    //桶
    Entry<K,V>[] table;

    //桶的实体,为链表
    private static class Entry<K,V> extends WeakReference<Object> implements Map.Entry<K,V> {
        //值
        V value;
        //哈希值
        final int hash;
        //下一个键值对
        Entry<K,V> next;
       //.....省略
    }


    /**
     * Retrieve object hash code and applies a supplemental hash function to the
     * result hash, which defends against poor quality hash functions.  This is
     * critical because HashMap uses power-of-two length hash tables, that
     * otherwise encounter collisions for hashCodes that do not differ
     * in lower bits.
     */
    //计算hash值
    final int hash(Object k) {
        int h = k.hashCode();

        // This function ensures that hashCodes that differ only by
        // constant multiples at each bit position have a bounded
        // number of collisions (approximately 8 at default load factor).
        h ^= (h >>> 20) ^ (h >>> 12);
        return h ^ (h >>> 7) ^ (h >>> 4);
    }


通过ReferenceQueue来保存要清除的对象,每次调用put、或者get等等方法都会先执行expungeStateEntries这个方法,通过这个方法把要清除的对象清除

    /**
     * Reference queue for cleared WeakEntries
     */
    //引用队列,用来存储要清除的键值对
    private final ReferenceQueue<Object> queue = new ReferenceQueue<>(); 

   /**
     * Expunges stale entries from the table.
     */
    //除去旧的键值对
    private void expungeStaleEntries() {
        //要清除对象存放在queue中,遍历queue中的键值对,然后清除掉
        for (Object x; (x = queue.poll()) != null; ) {
            //锁住存放要清除的键值对的queue
            synchronized (queue) {
                @SuppressWarnings("unchecked")
                    Entry<K,V> e = (Entry<K,V>) x;
                //计算得到要清除的键值对存放在table中的下标
                int i = indexFor(e.hash, table.length);

                Entry<K,V> prev = table[i];
                Entry<K,V> p = prev;
                //在table[i]这个桶中查找要清除的键值对e
                while (p != null) {
                    //在桶中遍历直到找到e
                    Entry<K,V> next = p.next;
                    if (p == e) {
                        if (prev == e)
                            //是桶的第一个元素,直接改变table[i]
                            table[i] = next;
                        else
                            //非桶第一个元素,设置next
                            prev.next = next;
                        // Must not null out e.next;
                        // stale entries may be in use by a HashIterator
                        e.value = null; // Help GC
                        //数量减一
                        size--;
                        break;
                    }
                    prev = p;
                    p = next;
                }
            }
        }
    }

通过key的hash值去跟桶容量做与运算来得到键值对存放的桶的位置的下标

    /**
     * Returns index for hash code h.
     */
    //h为hash值,计算的h下标
    private static int indexFor(int h, int length) {
        //通过hash值和长度去做与运算得到下标
        return h & (length-1);
    }

5、其他讲解

当key为null时,其实并不是把null真正设到Entry<K, V>中,而是将null设为NULL_KEY对象,将该对象设置到Entry<K, V>

    /**
     * Value representing null keys inside tables.
     */
    //NULL_KEY代表null的key
    private static final Object NULL_KEY = new Object();

    /**
     * Use NULL_KEY for key if it is null.
     */
    //当key==null时,用NULL_KEY对象代替
    private static Object maskNull(Object key) {
        return (key == null) ? NULL_KEY : key;
    }

    /**
     * Returns internal representation of null key back to caller as null.
     */
    //当key==NULL_KEY,转为原来的null
    static Object unmaskNull(Object key) {
        return (key == NULL_KEY) ? null : key;
    }

6、源代码及个人理解注释

/*
 * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */

package java.util;

import java.lang.ref.WeakReference;
import java.lang.ref.ReferenceQueue;
import java.util.concurrent.ThreadLocalRandom;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;


/**
 * Hash table based implementation of the <tt>Map</tt> interface, with
 * <em>weak keys</em>.
 * An entry in a <tt>WeakHashMap</tt> will automatically be removed when
 * its key is no longer in ordinary use.  More precisely, the presence of a
 * mapping for a given key will not prevent the key from being discarded by the
 * garbage collector, that is, made finalizable, finalized, and then reclaimed.
 * When a key has been discarded its entry is effectively removed from the map,
 * so this class behaves somewhat differently from other <tt>Map</tt>
 * implementations.
 *
 * <p> Both null values and the null key are supported. This class has
 * performance characteristics similar to those of the <tt>HashMap</tt>
 * class, and has the same efficiency parameters of <em>initial capacity</em>
 * and <em>load factor</em>.
 *
 * <p> Like most collection classes, this class is not synchronized.
 * A synchronized <tt>WeakHashMap</tt> may be constructed using the
 * {@link Collections#synchronizedMap Collections.synchronizedMap}
 * method.
 *
 * <p> This class is intended primarily for use with key objects whose
 * <tt>equals</tt> methods test for object identity using the
 * <tt>==</tt> operator.  Once such a key is discarded it can never be
 * recreated, so it is impossible to do a lookup of that key in a
 * <tt>WeakHashMap</tt> at some later time and be surprised that its entry
 * has been removed.  This class will work perfectly well with key objects
 * whose <tt>equals</tt> methods are not based upon object identity, such
 * as <tt>String</tt> instances.  With such recreatable key objects,
 * however, the automatic removal of <tt>WeakHashMap</tt> entries whose
 * keys have been discarded may prove to be confusing.
 *
 * <p> The behavior of the <tt>WeakHashMap</tt> class depends in part upon
 * the actions of the garbage collector, so several familiar (though not
 * required) <tt>Map</tt> invariants do not hold for this class.  Because
 * the garbage collector may discard keys at any time, a
 * <tt>WeakHashMap</tt> may behave as though an unknown thread is silently
 * removing entries.  In particular, even if you synchronize on a
 * <tt>WeakHashMap</tt> instance and invoke none of its mutator methods, it
 * is possible for the <tt>size</tt> method to return smaller values over
 * time, for the <tt>isEmpty</tt> method to return <tt>false</tt> and
 * then <tt>true</tt>, for the <tt>containsKey</tt> method to return
 * <tt>true</tt> and later <tt>false</tt> for a given key, for the
 * <tt>get</tt> method to return a value for a given key but later return
 * <tt>null</tt>, for the <tt>put</tt> method to return
 * <tt>null</tt> and the <tt>remove</tt> method to return
 * <tt>false</tt> for a key that previously appeared to be in the map, and
 * for successive examinations of the key set, the value collection, and
 * the entry set to yield successively smaller numbers of elements.
 *
 * <p> Each key object in a <tt>WeakHashMap</tt> is stored indirectly as
 * the referent of a weak reference.  Therefore a key will automatically be
 * removed only after the weak references to it, both inside and outside of the
 * map, have been cleared by the garbage collector.
 *
 * <p> <strong>Implementation note:</strong> The value objects in a
 * <tt>WeakHashMap</tt> are held by ordinary strong references.  Thus care
 * should be taken to ensure that value objects do not strongly refer to their
 * own keys, either directly or indirectly, since that will prevent the keys
 * from being discarded.  Note that a value object may refer indirectly to its
 * key via the <tt>WeakHashMap</tt> itself; that is, a value object may
 * strongly refer to some other key object whose associated value object, in
 * turn, strongly refers to the key of the first value object.  If the values
 * in the map do not rely on the map holding strong references to them, one way
 * to deal with this is to wrap values themselves within
 * <tt>WeakReferences</tt> before
 * inserting, as in: <tt>m.put(key, new WeakReference(value))</tt>,
 * and then unwrapping upon each <tt>get</tt>.
 *
 * <p>The iterators returned by the <tt>iterator</tt> method of the collections
 * returned by all of this class's "collection view methods" are
 * <i>fail-fast</i>: if the map is structurally modified at any time after the
 * iterator is created, in any way except through the iterator's own
 * <tt>remove</tt> method, the iterator will throw a {@link
 * ConcurrentModificationException}.  Thus, in the face of concurrent
 * modification, the iterator fails quickly and cleanly, rather than risking
 * arbitrary, non-deterministic behavior at an undetermined time in the future.
 *
 * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
 * as it is, generally speaking, impossible to make any hard guarantees in the
 * presence of unsynchronized concurrent modification.  Fail-fast iterators
 * throw <tt>ConcurrentModificationException</tt> on a best-effort basis.
 * Therefore, it would be wrong to write a program that depended on this
 * exception for its correctness:  <i>the fail-fast behavior of iterators
 * should be used only to detect bugs.</i>
 *
 * <p>This class is a member of the
 * <a href="{@docRoot}/../technotes/guides/collections/index.html">
 * Java Collections Framework</a>.
 *
 * @param <K> the type of keys maintained by this map
 * @param <V> the type of mapped values
 *
 * @author      Doug Lea
 * @author      Josh Bloch
 * @author      Mark Reinhold
 * @since       1.2
 * @see         java.util.HashMap
 * @see         java.lang.ref.WeakReference
 */
/*
以弱键 实现的基于哈希表的 Map。在 WeakHashMap 中,当某个键不再正常使用时,将自动移除其条目。更精确地说,
对于一个给定的键,其映射的存在并不阻止垃圾回收器对该键的丢弃,这就使该键成为可终止的,被终止,然后被回收。
丢弃某个键时,其条目从映射中有效地移除,因此,该类的行为与其他的 Map 实现有所不同。

null 值和 null 键都被支持。该类具有与 HashMap 类相似的性能特征,并具有相同的效能参数初始容量 和加载因子。

像大多数 collection 类一样,该类是不同步的。可以使用 Collections.synchronizedMap 方法来构造同步的 WeakHashMap。

该类主要与这样的键对象一起使用,其 equals 方法使用 == 运算符来测试对象标识。一旦这种键被丢弃,就永远无法再创建了,
所以,过段时间后在 WeakHashMap 中查找此键是不可能的,不必对其项已移除而感到惊讶。
该类十分适合与 equals 方法不是基于对象标识的键对象一起使用,比如,String 实例。
然而,对于这种可重新创建的键对象,键若丢弃,就自动移除 WeakHashMap 条目,这种表现令人疑惑。

WeakHashMap 类的行为部分取决于垃圾回收器的动作,所以,几个常见的(虽然不是必需的)Map 常量不支持此类。
因为垃圾回收器在任何时候都可能丢弃键,WeakHashMap 就像是一个被悄悄移除条目的未知线程。
特别地,即使对 WeakHashMap 实例进行同步,并且没有调用任何赋值方法,在一段时间后 size 方法也可能返回较小的值,
对于 isEmpty 方法,返回 false,然后返回 true,对于给定的键,containsKey 方法返回 true 然后返回 false,
对于给定的键,get 方法返回一个值,但接着返回 null,对于以前出现在映射中的键,put 方法返回 null,
而 remove 方法返回 false,对于键 set、值 collection 和条目 set 进行的检查,生成的元素数量越来越少。

WeakHashMap 中的每个键对象间接地存储为一个弱引用的指示对象。因此,不管是在映射内还是在映射之外,
只有在垃圾回收器清除某个键的弱引用之后,该键才会自动移除。

实现注意事项:WeakHashMap 中的值对象由普通的强引用保持。因此应该小心谨慎,
确保值对象不会直接或间接地强引用其自身的键,因为这会阻止键的丢弃。注意,
值对象可以通过 WeakHashMap 本身间接引用其对应的键;这就是说,某个值对象可能强引用某个其他的键对象,
而与该键对象相关联的值对象转而强引用第一个值对象的键。处理此问题的一种方法是,
在插入前将值自身包装在 WeakReferences 中,如:m.put(key, new WeakReference(value)),然后,分别用 get 进行解包。

collection 的 iterator 方法所返回的迭代器(由该类所有“collection 视图方法”返回)均是快速失败的:
在迭代器创建之后,如果从结构上对映射进行修改,除非通过迭代器自身的 remove 或 add 方法,
其他任何时间任何方式的修改,迭代器都将抛出 ConcurrentModificationException。因此,
面对并发的修改,迭代器很快就完全失败,而不是冒着在将来不确定的时间任意发生不确定行为的风险。

注意,迭代器的快速失败行为不能得到保证,一般来说,存在不同步的并发修改时,不可能作出任何坚决的保证。
快速失败迭代器尽最大努力抛出 ConcurrentModificationException。
因此,编写依赖于此异常程序的方式是错误的,正确做法是:迭代器的快速失败行为应该仅用于检测 bug。
 */
public class WeakHashMap<K,V>
    extends AbstractMap<K,V>
    implements Map<K,V> {

    /**
     * The default initial capacity -- MUST be a power of two.
     */
    //默认的初始化容量为16
    private static final int DEFAULT_INITIAL_CAPACITY = 16;

    /**
     * The maximum capacity, used if a higher value is implicitly specified
     * by either of the constructors with arguments.
     * MUST be a power of two <= 1<<30.
     */
    //最大容量为 2^30
    private static final int MAXIMUM_CAPACITY = 1 << 30;

    /**
     * The load factor used when none specified in constructor.
     */
    //默认的加载因子为0.75f
    private static final float DEFAULT_LOAD_FACTOR = 0.75f;

    /**
     * The table, resized as necessary. Length MUST Always be a power of two.
     */
    //桶
    Entry<K,V>[] table;

    /**
     * The number of key-value mappings contained in this weak hash map.
     */
    //键值对的数量
    private int size;

    /**
     * The next size value at which to resize (capacity * load factor).
     */
    //要扩展的阀值
    private int threshold;

    /**
     * The load factor for the hash table.
     */
    //加载因子
    private final float loadFactor;

    /**
     * Reference queue for cleared WeakEntries
     */
    //引用队列,用来存储要清除的键值对
    private final ReferenceQueue<Object> queue = new ReferenceQueue<>();

    /**
     * The number of times this WeakHashMap has been structurally modified.
     * Structural modifications are those that change the number of
     * mappings in the map or otherwise modify its internal structure
     * (e.g., rehash).  This field is used to make iterators on
     * Collection-views of the map fail-fast.
     *
     * @see ConcurrentModificationException
     */
    //修改时自增一,检测是否有并发修改
    int modCount;

    //创建缓冲区
    @SuppressWarnings("unchecked")
    private Entry<K,V>[] newTable(int n) {
        //Entry<K,V>[] 是桶的数组
        return (Entry<K,V>[]) new Entry<?,?>[n];
    }

    /**
     * Constructs a new, empty <tt>WeakHashMap</tt> with the given initial
     * capacity and the given load factor.
     *
     * @param  initialCapacity The initial capacity of the <tt>WeakHashMap</tt>
     * @param  loadFactor      The load factor of the <tt>WeakHashMap</tt>
     * @throws IllegalArgumentException if the initial capacity is negative,
     *         or if the load factor is nonpositive.
     */
    //构造方法,传入初始化容量,加载因子
    public WeakHashMap(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);
        int capacity = 1;
        //循环左移,使初始化容量大于initialCapacity,且为2的n次方
        while (capacity < initialCapacity)
            capacity <<= 1;
        //初始化桶数组
        table = newTable(capacity);
        //赋值加载因子
        this.loadFactor = loadFactor;
        //计算扩容阀值
        threshold = (int)(capacity * loadFactor);
    }

    /**
     * Constructs a new, empty <tt>WeakHashMap</tt> with the given initial
     * capacity and the default load factor (0.75).
     *
     * @param  initialCapacity The initial capacity of the <tt>WeakHashMap</tt>
     * @throws IllegalArgumentException if the initial capacity is negative
     */
    //构造方法,传入初始化容量,加载因子为默认0.75f
    public WeakHashMap(int initialCapacity) {
        this(initialCapacity, DEFAULT_LOAD_FACTOR);
    }

    /**
     * Constructs a new, empty <tt>WeakHashMap</tt> with the default initial
     * capacity (16) and load factor (0.75).
     */
    //构造方法,用默认的初始化容量 16 和加载因子 0.75
    public WeakHashMap() {
        this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR);
    }

    /**
     * Constructs a new <tt>WeakHashMap</tt> with the same mappings as the
     * specified map.  The <tt>WeakHashMap</tt> is created with the default
     * load factor (0.75) and an initial capacity sufficient to hold the
     * mappings in the specified map.
     *
     * @param   m the map whose mappings are to be placed in this map
     * @throws  NullPointerException if the specified map is null
     * @since   1.3
     */
    //构造方法,有初始键值对
    public WeakHashMap(Map<? extends K, ? extends V> m) {
        //初始化容量为m的容量/加载因子+1,相当于初始化后容量刚好到达阀值
        this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1,
                DEFAULT_INITIAL_CAPACITY),
             DEFAULT_LOAD_FACTOR);
        //初始化键值对
        putAll(m);
    }

    // internal utilities

    /**
     * Value representing null keys inside tables.
     */
    //NULL_KEY代表null的key
    private static final Object NULL_KEY = new Object();

    /**
     * Use NULL_KEY for key if it is null.
     */
    //当key==null时,用NULL_KEY对象代替
    private static Object maskNull(Object key) {
        return (key == null) ? NULL_KEY : key;
    }

    /**
     * Returns internal representation of null key back to caller as null.
     */
    //当key==NULL_KEY,转为原来的null
    static Object unmaskNull(Object key) {
        return (key == NULL_KEY) ? null : key;
    }

    /**
     * Checks for equality of non-null reference x and possibly-null y.  By
     * default uses Object.equals.
     */
    //判断2个对象是否相等
    private static boolean eq(Object x, Object y) {
        return x == y || x.equals(y);
    }

    /**
     * Retrieve object hash code and applies a supplemental hash function to the
     * result hash, which defends against poor quality hash functions.  This is
     * critical because HashMap uses power-of-two length hash tables, that
     * otherwise encounter collisions for hashCodes that do not differ
     * in lower bits.
     */
    //计算hash值
    final int hash(Object k) {
        int h = k.hashCode();

        // This function ensures that hashCodes that differ only by
        // constant multiples at each bit position have a bounded
        // number of collisions (approximately 8 at default load factor).
        h ^= (h >>> 20) ^ (h >>> 12);
        return h ^ (h >>> 7) ^ (h >>> 4);
    }

    /**
     * Returns index for hash code h.
     */
    //h为hash值,计算的h下标
    private static int indexFor(int h, int length) {
        //通过hash值和长度去做与运算得到下标
        return h & (length-1);
    }

    /**
     * Expunges stale entries from the table.
     */
    //除去旧的键值对
    private void expungeStaleEntries() {
        //要清除对象存放在queue中,遍历queue中的键值对,然后清除掉
        for (Object x; (x = queue.poll()) != null; ) {
            //锁住存放要清除的键值对的queue
            synchronized (queue) {
                @SuppressWarnings("unchecked")
                    Entry<K,V> e = (Entry<K,V>) x;
                //计算得到要清除的键值对存放在table中的下标
                int i = indexFor(e.hash, table.length);

                Entry<K,V> prev = table[i];
                Entry<K,V> p = prev;
                //在table[i]这个桶中查找要清除的键值对e
                while (p != null) {
                    //在桶中遍历直到找到e
                    Entry<K,V> next = p.next;
                    if (p == e) {
                        if (prev == e)
                            //是桶的第一个元素,直接改变table[i]
                            table[i] = next;
                        else
                            //非桶第一个元素,设置next
                            prev.next = next;
                        // Must not null out e.next;
                        // stale entries may be in use by a HashIterator
                        e.value = null; // Help GC
                        //数量减一
                        size--;
                        break;
                    }
                    prev = p;
                    p = next;
                }
            }
        }
    }

    /**
     * Returns the table after first expunging stale entries.
     */
    //获取table
    private Entry<K,V>[] getTable() {
        //清除掉没用的对象后在返回table
        expungeStaleEntries();
        return table;
    }

    /**
     * Returns the number of key-value mappings in this map.
     * This result is a snapshot, and may not reflect unprocessed
     * entries that will be removed before next attempted access
     * because they are no longer referenced.
     */
    //获取size
    public int size() {
        if (size == 0)
            return 0;
        //清除掉没用的对象
        expungeStaleEntries();
        return size;
    }

    /**
     * Returns <tt>true</tt> if this map contains no key-value mappings.
     * This result is a snapshot, and may not reflect unprocessed
     * entries that will be removed before next attempted access
     * because they are no longer referenced.
     */
    //判断是否为空
    public boolean isEmpty() {
        return size() == 0;
    }

    /**
     * Returns the value to which the specified key is mapped,
     * or {@code null} if this map contains no mapping for the key.
     *
     * <p>More formally, if this map contains a mapping from a key
     * {@code k} to a value {@code v} such that {@code (key==null ? k==null :
     * key.equals(k))}, then this method returns {@code v}; otherwise
     * it returns {@code null}.  (There can be at most one such mapping.)
     *
     * <p>A return value of {@code null} does not <i>necessarily</i>
     * indicate that the map contains no mapping for the key; it's also
     * possible that the map explicitly maps the key to {@code null}.
     * The {@link #containsKey containsKey} operation may be used to
     * distinguish these two cases.
     *
     * @see #put(Object, Object)
     */
    //通过key获取value
    public V get(Object key) {
        //key如果是null,则返回NULL_KEY
        Object k = maskNull(key);
        //获取k的hashCode
        int h = hash(k);
        //获取当前的
        Entry<K,V>[] tab = getTable();
        //通过key的hash找到存放的桶的下标
        int index = indexFor(h, tab.length);
        //存放hash值为h的桶
        Entry<K,V> e = tab[index];
        while (e != null) {
            //在桶中查找键为key的键值对
            if (e.hash == h && eq(k, e.get()))
                //hash相同且引用对象相同
                return e.value;
            e = e.next;
        }
        return null;
    }

    /**
     * Returns <tt>true</tt> if this map contains a mapping for the
     * specified key.
     *
     * @param  key   The key whose presence in this map is to be tested
     * @return <tt>true</tt> if there is a mapping for <tt>key</tt>;
     *         <tt>false</tt> otherwise
     */
    //判断是否包含键为key的键值对
    public boolean containsKey(Object key) {
        return getEntry(key) != null;
    }

    /**
     * Returns the entry associated with the specified key in this map.
     * Returns null if the map contains no mapping for this key.
     */
    //通过key获取键值对
    Entry<K,V> getEntry(Object key) {
        //如果key为null则返回NULL_KEY,获取真实存在哈希链表中的key
        Object k = maskNull(key);
        //计算hashCode
        int h = hash(k);
        //当前桶的对象
        Entry<K,V>[] tab = getTable();
        //得到存放哈希值为h的桶的下标
        int index = indexFor(h, tab.length);
        //获取存放哈希值为h的桶
        Entry<K,V> e = tab[index];
        while (e != null && !(e.hash == h && eq(k, e.get())))
            //在桶中遍历查找
            e = e.next;
        return e;
    }

    /**
     * Associates the specified value with the specified key in this map.
     * If the map previously contained a mapping for this key, the old
     * value is replaced.
     *
     * @param key key with which the specified value is to be associated.
     * @param value value to be associated with the specified key.
     * @return the previous value associated with <tt>key</tt>, or
     *         <tt>null</tt> if there was no mapping for <tt>key</tt>.
     *         (A <tt>null</tt> return can also indicate that the map
     *         previously associated <tt>null</tt> with <tt>key</tt>.)
     */
    //添加键值对
    public V put(K key, V value) {
        //如果key为null,则返回NULL_KEY
        Object k = maskNull(key);
        //计算key的hash值
        int h = hash(k);
        //获取当前的桶数组table
        Entry<K,V>[] tab = getTable();
        //计算得到存放哈希值为h的下标
        int i = indexFor(h, tab.length);

        //在桶中循环遍历查找是否有相同的key,如果有则赋新value
        for (Entry<K,V> e = tab[i]; e != null; e = e.next) {
            if (h == e.hash && eq(k, e.get())) {
                //查找到有相同key的键值对
                V oldValue = e.value;
                //value不同的话就赋新值
                if (value != oldValue)
                    e.value = value;
                return oldValue;
            }
        }

        modCount++;
        Entry<K,V> e = tab[i];
        //在桶中添加一个键值对
        tab[i] = new Entry<>(k, value, queue, h, e);
        if (++size >= threshold)
            //到达阀值则扩容原来的2被
            resize(tab.length * 2);
        return null;
    }

    /**
     * Rehashes the contents of this map into a new array with a
     * larger capacity.  This method is called automatically when the
     * number of keys in this map reaches its threshold.
     *
     * If current capacity is MAXIMUM_CAPACITY, this method does not
     * resize the map, but sets threshold to Integer.MAX_VALUE.
     * This has the effect of preventing future calls.
     *
     * @param newCapacity the new capacity, MUST be a power of two;
     *        must be greater than current capacity unless current
     *        capacity is MAXIMUM_CAPACITY (in which case value
     *        is irrelevant).
     */
    //扩容
    void resize(int newCapacity) {
        //获取旧的桶table
        Entry<K,V>[] oldTable = getTable();
        //记录旧的桶的容量
        int oldCapacity = oldTable.length;
        if (oldCapacity == MAXIMUM_CAPACITY) {
            //当旧容量已经是最大容量时,将阀值设为Integer.MAX_VALUE
            threshold = Integer.MAX_VALUE;
            return;
        }

        //创建新的桶table
        Entry<K,V>[] newTable = newTable(newCapacity);
        //将旧的桶中的键值对赋到新的桶
        transfer(oldTable, newTable);
        table = newTable;

        /*
         * If ignoring null elements and processing ref queue caused massive
         * shrinkage, then restore old table.  This should be rare, but avoids
         * unbounded expansion of garbage-filled tables.
         */
        if (size >= threshold / 2) {
            //如果原来的键值对数量已经超过阀值的1/2,则重新设置阀值
            threshold = (int)(newCapacity * loadFactor);
        } else {
            //键值对没有超过阀值的1/2,则将table设置为oldTable
            //这种情况出现几率很小,可能是queue中回收对象太多导致
            expungeStaleEntries();
            transfer(newTable, oldTable);
            table = oldTable;
        }
    }

    /** Transfers all entries from src to dest tables */
    //将src中的对象复制到dest中
    private void transfer(Entry<K,V>[] src, Entry<K,V>[] dest) {
        //遍历src数组
        for (int j = 0; j < src.length; ++j) {
            Entry<K,V> e = src[j];
            src[j] = null;
            while (e != null) {
                //遍历桶中的整个链表
                Entry<K,V> next = e.next;
                Object key = e.get();
                if (key == null) {
                    //到了链表末尾
                    e.next = null;  // Help GC
                    e.value = null; //  "   "
                    size--;
                } else {
                    //未到链表末尾
                    //获取插入dest的位置下标
                    int i = indexFor(e.hash, dest.length);
                    //将e插入到桶的第一个元素
                    e.next = dest[i];
                    dest[i] = e;
                }
                e = next;
            }
        }
    }

    /**
     * Copies all of the mappings from the specified map to this map.
     * These mappings will replace any mappings that this map had for any
     * of the keys currently in the specified map.
     *
     * @param m mappings to be stored in this map.
     * @throws  NullPointerException if the specified map is null.
     */
    //将所有m中的键值对赋到本map中
    public void putAll(Map<? extends K, ? extends V> m) {
        int numKeysToBeAdded = m.size();
        //如果键值对数量为0则返回
        if (numKeysToBeAdded == 0)
            return;

        /*
         * Expand the map if the map if the number of mappings to be added
         * is greater than or equal to threshold.  This is conservative; the
         * obvious condition is (m.size() + size) >= threshold, but this
         * condition could result in a map with twice the appropriate capacity,
         * if the keys to be added overlap with the keys already in this map.
         * By using the conservative calculation, we subject ourself
         * to at most one extra resize.
         */
        //如果要添加的数量大于阀值,则需要扩容
        if (numKeysToBeAdded > threshold) {
            //计算新容量
            int targetCapacity = (int)(numKeysToBeAdded / loadFactor + 1);
            //容量最大为MAXIMUM_CAPACITY
            if (targetCapacity > MAXIMUM_CAPACITY)
                targetCapacity = MAXIMUM_CAPACITY;
            int newCapacity = table.length;
            //保证新的容量为2的次方
            while (newCapacity < targetCapacity)
                newCapacity <<= 1;
            if (newCapacity > table.length)
                //扩容
                resize(newCapacity);
        }

        //put每个<key,value>
        for (Map.Entry<? extends K, ? extends V> e : m.entrySet())
            put(e.getKey(), e.getValue());
    }

    /**
     * Removes the mapping for a key from this weak hash map if it is present.
     * More formally, if this map contains a mapping from key <tt>k</tt> to
     * value <tt>v</tt> such that <code>(key==null ?  k==null :
     * key.equals(k))</code>, that mapping is removed.  (The map can contain
     * at most one such mapping.)
     *
     * <p>Returns the value to which this map previously associated the key,
     * or <tt>null</tt> if the map contained no mapping for the key.  A
     * return value of <tt>null</tt> does not <i>necessarily</i> indicate
     * that the map contained no mapping for the key; it's also possible
     * that the map explicitly mapped the key to <tt>null</tt>.
     *
     * <p>The map will not contain a mapping for the specified key once the
     * call returns.
     *
     * @param key key whose mapping is to be removed from the map
     * @return the previous value associated with <tt>key</tt>, or
     *         <tt>null</tt> if there was no mapping for <tt>key</tt>
     */
    //移除掉键为key的键值对
    public V remove(Object key) {
        //返回不为null的对象,k==null则返回NULL_KEY对象
        Object k = maskNull(key);
        //计算hash值
        int h = hash(k);
        //获取桶数组table
        Entry<K,V>[] tab = getTable();
        //计算下标
        int i = indexFor(h, tab.length);
        Entry<K,V> prev = tab[i];
        Entry<K,V> e = prev;

        //遍历链表
        while (e != null) {
            Entry<K,V> next = e.next;
            //找到相应的键值对
            if (h == e.hash && eq(k, e.get())) {
                modCount++;
                //容量减一
                size--;
                if (prev == e)
                    //remove的键值对是桶第一个对象
                    tab[i] = next;
                else
                    //remove的键值对非桶第一个对象
                    prev.next = next;
                return e.value;
            }
            //往后移
            prev = e;
            e = next;
        }

        return null;
    }

    /** Special version of remove needed by Entry set */
    //移除键值对,o为键值对
    boolean removeMapping(Object o) {
        if (!(o instanceof Map.Entry))
            //不是Map.Entry则返回false
            return false;
        //获取桶数组
        Entry<K,V>[] tab = getTable();
        Map.Entry<?,?> entry = (Map.Entry<?,?>)o;
        //获取key
        Object k = maskNull(entry.getKey());
        //计算hash值
        int h = hash(k);
        //计算存放在桶table中的下标
        int i = indexFor(h, tab.length);
        Entry<K,V> prev = tab[i];
        Entry<K,V> e = prev;

        while (e != null) {
            //遍历链表
            Entry<K,V> next = e.next;
            if (h == e.hash && e.equals(entry)) {
                //查找到对象的键值对
                modCount++;
                size--;
                if (prev == e)
                    //查找到的键值对为桶中第一个元素
                    tab[i] = next;
                else
                    //非桶中第一个元素
                    prev.next = next;
                return true;
            }
            prev = e;
            e = next;
        }

        return false;
    }

    /**
     * Removes all of the mappings from this map.
     * The map will be empty after this call returns.
     */
    //清除掉键值对
    public void clear() {
        // clear out ref queue. We don't need to expunge entries
        // since table is getting cleared.
        //先将队列中的键值对清除
        while (queue.poll() != null)
            ;

        modCount++;
        //将table数组设为null
        Arrays.fill(table, null);
        size = 0;

        // Allocation of array may have caused GC, which may have caused
        // additional entries to go stale.  Removing these entries from the
        // reference queue will make them eligible for reclamation.
        while (queue.poll() != null)
            ;
    }

    /**
     * Returns <tt>true</tt> if this map maps one or more keys to the
     * specified value.
     *
     * @param value value whose presence in this map is to be tested
     * @return <tt>true</tt> if this map maps one or more keys to the
     *         specified value
     */
    //判断是否包含值为value
    public boolean containsValue(Object value) {
        if (value==null)
            //value为空则调用另一个方法
            return containsNullValue();

        //获取桶数组table
        Entry<K,V>[] tab = getTable();
        for (int i = tab.length; i-- > 0;)
            //遍历桶
            for (Entry<K,V> e = tab[i]; e != null; e = e.next)
                //遍历桶中的链表
                if (value.equals(e.value))
                    return true;
        return false;
    }

    /**
     * Special-case code for containsValue with null argument
     */
    //null则通过 == 来对比
    private boolean containsNullValue() {
        Entry<K,V>[] tab = getTable();
        for (int i = tab.length; i-- > 0;)
            //遍历桶
            for (Entry<K,V> e = tab[i]; e != null; e = e.next)
                //遍历链表
                if (e.value==null)
                    return true;
        return false;
    }

    /**
     * The entries in this hash table extend WeakReference, using its main ref
     * field as the key.
     */
    //键值对类
    private static class Entry<K,V> extends WeakReference<Object> implements Map.Entry<K,V> {
        //值
        V value;
        //哈希值
        final int hash;
        //下一个键值对
        Entry<K,V> next;

        /**
         * Creates new entry.
         */
        Entry(Object key, V value,
              ReferenceQueue<Object> queue,
              int hash, Entry<K,V> next) {
            super(key, queue);
            this.value = value;
            this.hash  = hash;
            this.next  = next;
        }

        //获取key
        @SuppressWarnings("unchecked")
        public K getKey() {
            return (K) WeakHashMap.unmaskNull(get());
        }

        //获取值
        public V getValue() {
            return value;
        }

        //设置值
        public V setValue(V newValue) {
            V oldValue = value;
            value = newValue;
            return oldValue;
        }

        //判断键值对是否相同
        public boolean equals(Object o) {
            if (!(o instanceof Map.Entry))
                return false;
            Map.Entry<?,?> e = (Map.Entry<?,?>)o;
            K k1 = getKey();
            Object k2 = e.getKey();
            if (k1 == k2 || (k1 != null && k1.equals(k2))) {
                //比较key
                V v1 = getValue();
                Object v2 = e.getValue();
                if (v1 == v2 || (v1 != null && v1.equals(v2)))
                    //比较value
                    return true;
            }
            return false;
        }

        //计算hash值
        public int hashCode() {
            K k = getKey();
            V v = getValue();
            //将key和value各自的hash值异或
            return Objects.hashCode(k) ^ Objects.hashCode(v);
        }

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

    //hash迭代器
    private abstract class HashIterator<T> implements Iterator<T> {
        //下一个键值对的下标
        private int index;
        //下一个键值对对象
        private Entry<K,V> entry = null;
        //上一个返回的键值对对象
        private Entry<K,V> lastReturned = null;
        private int expectedModCount = modCount;

        /**
         * Strong reference needed to avoid disappearance of key
         * between hasNext and next
         */
        //下一个key,强引用,防止在调用hasNext和next之间key消失
        private Object nextKey = null;

        /**
         * Strong reference needed to avoid disappearance of key
         * between nextEntry() and any use of the entry
         */
        //当前的键值对的key
        private Object currentKey = null;

        HashIterator() {
            index = isEmpty() ? 0 : table.length;
        }

        //判断是否还有对象
        public boolean hasNext() {
            Entry<K,V>[] t = table;

            while (nextKey == null) {
                Entry<K,V> e = entry;
                int i = index;
                while (e == null && i > 0)
                    //循环,直到桶不为空
                    e = t[--i];
                entry = e;
                index = i;
                if (e == null) {
                    //没有对象了
                    currentKey = null;
                    return false;
                }
                //获取下一个对象的key
                nextKey = e.get(); // hold on to key in strong ref
                if (nextKey == null)
                    entry = entry.next;
            }
            return true;
        }

        /** The common parts of next() across different types of iterators */
        //获取下一个键值对
        protected Entry<K,V> nextEntry() {
            if (modCount != expectedModCount)
                //检测并发
                throw new ConcurrentModificationException();
            if (nextKey == null && !hasNext())
                //没有键值对
                throw new NoSuchElementException();

            //修改各个变量
            lastReturned = entry;
            entry = entry.next;
            currentKey = nextKey;
            nextKey = null;
            return lastReturned;
        }

        //移除掉元素
        public void remove() {
            if (lastReturned == null)
                throw new IllegalStateException();
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();

            //移除掉当前的对象
            WeakHashMap.this.remove(currentKey);
            expectedModCount = modCount;
            lastReturned = null;
            currentKey = null;
        }

    }

    //值的迭代器
    private class ValueIterator extends HashIterator<V> {
        public V next() {
            //获取键值对的value
            return nextEntry().value;
        }
    }

    //键的迭代器
    private class KeyIterator extends HashIterator<K> {
        public K next() {
            //获取键值对的key
            return nextEntry().getKey();
        }
    }

    //键值对的迭代器
    private class EntryIterator extends HashIterator<Map.Entry<K,V>> {
        public Map.Entry<K,V> next() {
            return nextEntry();
        }
    }

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

    //获取keySet
    private class KeySet extends AbstractSet<K> {
        //获取key的迭代器
        public Iterator<K> iterator() {
            return new KeyIterator();
        }

        //获取size
        public int size() {
            return WeakHashMap.this.size();
        }

        public boolean contains(Object o) {
            //判断是否包含key为o的键值对
            return containsKey(o);
        }

        //移除掉key为o的键值对
        public boolean remove(Object o) {
            if (containsKey(o)) {
                WeakHashMap.this.remove(o);
                return true;
            }
            else
                return false;
        }

        //清除键值对
        public void clear() {
            WeakHashMap.this.clear();
        }

        public Spliterator<K> spliterator() {
            return new KeySpliterator<>(WeakHashMap.this, 0, -1, 0, 0);
        }
    }

    /**
     * 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.
     */
    //获取value组成的集合
    public Collection<V> values() {
        Collection<V> vs = values;
        return (vs != null) ? vs : (values = new Values());
    }

    //value的集合
    private class Values extends AbstractCollection<V> {
        //获取value迭代器
        public Iterator<V> iterator() {
            return new ValueIterator();
        }

        //获取value 的数量
        public int size() {
            return WeakHashMap.this.size();
        }

        //判断是否包含value为o的键值对
        public boolean contains(Object o) {
            return containsValue(o);
        }

        //清除键值对
        public void clear() {
            WeakHashMap.this.clear();
        }

        public Spliterator<V> spliterator() {
            return new ValueSpliterator<>(WeakHashMap.this, 0, -1, 0, 0);
        }
    }

    /**
     * Returns a {@link Set} view of the mappings 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, or through the
     * <tt>setValue</tt> operation on a map entry returned by the
     * iterator) 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.
     */
    //获取键值对的set
    public Set<Map.Entry<K,V>> entrySet() {
        Set<Map.Entry<K,V>> es = entrySet;
        return es != null ? es : (entrySet = new EntrySet());
    }

    //键值对的set
    private class EntrySet extends AbstractSet<Map.Entry<K,V>> {
        //获取键值对的迭代器
        public Iterator<Map.Entry<K,V>> iterator() {
            return new EntryIterator();
        }

        //判断是否包含o键值对
        public boolean contains(Object o) {
            if (!(o instanceof Map.Entry))
                //o不为键值对
                return false;
            Map.Entry<?,?> e = (Map.Entry<?,?>)o;
            Entry<K,V> candidate = getEntry(e.getKey());
            //判断是否相同
            return candidate != null && candidate.equals(e);
        }

        //移除掉键值对为o
        public boolean remove(Object o) {
            return removeMapping(o);
        }

        public int size() {
            return WeakHashMap.this.size();
        }

        public void clear() {
            WeakHashMap.this.clear();
        }

        //深度复制
        private List<Map.Entry<K,V>> deepCopy() {
            List<Map.Entry<K,V>> list = new ArrayList<>(size());
            //转为列表
            for (Map.Entry<K,V> e : this)
                //添加对象
                list.add(new AbstractMap.SimpleEntry<>(e));
            return list;
        }

        public Object[] toArray() {
            return deepCopy().toArray();
        }

        public <T> T[] toArray(T[] a) {
            return deepCopy().toArray(a);
        }

        public Spliterator<Map.Entry<K,V>> spliterator() {
            return new EntrySpliterator<>(WeakHashMap.this, 0, -1, 0, 0);
        }
    }

    //遍历所有键值对
    @SuppressWarnings("unchecked")
    @Override
    public void forEach(BiConsumer<? super K, ? super V> action) {
        Objects.requireNonNull(action);
        int expectedModCount = modCount;

        //获取桶
        Entry<K, V>[] tab = getTable();
        for (Entry<K, V> entry : tab) {
            //遍历桶
            while (entry != null) {
                //遍历桶中的键值对
                Object key = entry.get();
                if (key != null) {
                    //将键值对传递到action中
                    action.accept((K)WeakHashMap.unmaskNull(key), entry.value);
                }
                //下一个键值对
                entry = entry.next;

                if (expectedModCount != modCount) {
                    throw new ConcurrentModificationException();
                }
            }
        }
    }

    //替换所有的value
    @SuppressWarnings("unchecked")
    @Override
    public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
        Objects.requireNonNull(function);
        int expectedModCount = modCount;

        Entry<K, V>[] tab = getTable();;
        for (Entry<K, V> entry : tab) {
            //遍历所有桶
            while (entry != null) {
                //遍历桶中的键值对
                Object key = entry.get();
                if (key != null) {
                    //通过函数计算后设置新的value
                    entry.value = function.apply((K)WeakHashMap.unmaskNull(key), entry.value);
                }
                entry = entry.next;

                if (expectedModCount != modCount) {
                    throw new ConcurrentModificationException();
                }
            }
        }
    }

    /**
     * Similar form as other hash Spliterators, but skips dead
     * elements.
     */
    static class WeakHashMapSpliterator<K,V> {
        final WeakHashMap<K,V> map;
        //当前的键值对
        WeakHashMap.Entry<K,V> current; // current node
        //当前的键值对的下标
        int index;             // current index, modified on advance/split
        int fence;             // -1 until first use; then one past last index
        //估计大小
        int est;               // size estimate
        int expectedModCount;  // for comodification checks

        //构造方法
        WeakHashMapSpliterator(WeakHashMap<K,V> m, int origin,
                               int fence, int est,
                               int expectedModCount) {
            this.map = m;
            this.index = origin;
            this.fence = fence;
            this.est = est;
            this.expectedModCount = expectedModCount;
        }

        final int getFence() { // initialize fence and size on first use
            int hi;
            if ((hi = fence) < 0) {
                //初始化
                WeakHashMap<K,V> m = map;
                est = m.size();
                expectedModCount = m.modCount;
                hi = fence = m.table.length;
            }
            return hi;
        }

        public final long estimateSize() {
            getFence(); // force init
            return (long) est;
        }
    }

    static final class KeySpliterator<K,V>
        extends WeakHashMapSpliterator<K,V>
        implements Spliterator<K> {
        KeySpliterator(WeakHashMap<K,V> m, int origin, int fence, int est,
                       int expectedModCount) {
            super(m, origin, fence, est, expectedModCount);
        }

        public KeySpliterator<K,V> trySplit() {
            //分割
            int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
            return (lo >= mid) ? null :
                new KeySpliterator<K,V>(map, lo, index = mid, est >>>= 1,
                                        expectedModCount);
        }

        //遍历所有剩余的键值对
        public void forEachRemaining(Consumer<? super K> action) {
            int i, hi, mc;
            if (action == null)
                throw new NullPointerException();
            WeakHashMap<K,V> m = map;
            //桶数组
            WeakHashMap.Entry<K,V>[] tab = m.table;
            if ((hi = fence) < 0) {
                //初始化fence
                mc = expectedModCount = m.modCount;
                hi = fence = tab.length;
            }
            else
                mc = expectedModCount;
            if (tab.length >= hi && (i = index) >= 0 &&
                (i < (index = hi) || current != null)) {
                WeakHashMap.Entry<K,V> p = current;
                current = null; // exhaust
                do {
                    //遍历键值对
                    if (p == null)
                        p = tab[i++];
                    else {
                        Object x = p.get();
                        p = p.next;
                        if (x != null) {
                            @SuppressWarnings("unchecked") K k =
                                (K) WeakHashMap.unmaskNull(x);
                            //将key传到action中
                            action.accept(k);
                        }
                    }
                } while (p != null || i < hi);
            }
            if (m.modCount != mc)
                throw new ConcurrentModificationException();
        }

        //获取第一个元素
        public boolean tryAdvance(Consumer<? super K> action) {
            int hi;
            if (action == null)
                throw new NullPointerException();
            WeakHashMap.Entry<K,V>[] tab = map.table;
            if (tab.length >= (hi = getFence()) && index >= 0) {
                while (current != null || index < hi) {
                    if (current == null)
                        current = tab[index++];
                    else {
                        Object x = current.get();
                        current = current.next;
                        if (x != null) {
                            @SuppressWarnings("unchecked") K k =
                                (K) WeakHashMap.unmaskNull(x);
                            action.accept(k);
                            if (map.modCount != expectedModCount)
                                throw new ConcurrentModificationException();
                            return true;
                        }
                    }
                }
            }
            return false;
        }

        public int characteristics() {
            return Spliterator.DISTINCT;
        }
    }

    //类似KeySpliterator,只是将Key改为Value
    static final class ValueSpliterator<K,V>
        extends WeakHashMapSpliterator<K,V>
        implements Spliterator<V> {
        ValueSpliterator(WeakHashMap<K,V> m, int origin, int fence, int est,
                         int expectedModCount) {
            super(m, origin, fence, est, expectedModCount);
        }

        public ValueSpliterator<K,V> trySplit() {
            int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
            return (lo >= mid) ? null :
                new ValueSpliterator<K,V>(map, lo, index = mid, est >>>= 1,
                                          expectedModCount);
        }

        public void forEachRemaining(Consumer<? super V> action) {
            int i, hi, mc;
            if (action == null)
                throw new NullPointerException();
            WeakHashMap<K,V> m = map;
            WeakHashMap.Entry<K,V>[] tab = m.table;
            if ((hi = fence) < 0) {
                mc = expectedModCount = m.modCount;
                hi = fence = tab.length;
            }
            else
                mc = expectedModCount;
            if (tab.length >= hi && (i = index) >= 0 &&
                (i < (index = hi) || current != null)) {
                WeakHashMap.Entry<K,V> p = current;
                current = null; // exhaust
                do {
                    if (p == null)
                        p = tab[i++];
                    else {
                        Object x = p.get();
                        V v = p.value;
                        p = p.next;
                        if (x != null)
                            action.accept(v);
                    }
                } while (p != null || i < hi);
            }
            if (m.modCount != mc)
                throw new ConcurrentModificationException();
        }

        public boolean tryAdvance(Consumer<? super V> action) {
            int hi;
            if (action == null)
                throw new NullPointerException();
            WeakHashMap.Entry<K,V>[] tab = map.table;
            if (tab.length >= (hi = getFence()) && index >= 0) {
                while (current != null || index < hi) {
                    if (current == null)
                        current = tab[index++];
                    else {
                        Object x = current.get();
                        V v = current.value;
                        current = current.next;
                        if (x != null) {
                            action.accept(v);
                            if (map.modCount != expectedModCount)
                                throw new ConcurrentModificationException();
                            return true;
                        }
                    }
                }
            }
            return false;
        }

        public int characteristics() {
            return 0;
        }
    }

    //类似KeySpliterator,将key改为<key,value>
    static final class EntrySpliterator<K,V>
        extends WeakHashMapSpliterator<K,V>
        implements Spliterator<Map.Entry<K,V>> {
        EntrySpliterator(WeakHashMap<K,V> m, int origin, int fence, int est,
                       int expectedModCount) {
            super(m, origin, fence, est, expectedModCount);
        }

        public EntrySpliterator<K,V> trySplit() {
            int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
            return (lo >= mid) ? null :
                new EntrySpliterator<K,V>(map, lo, index = mid, est >>>= 1,
                                          expectedModCount);
        }


        public void forEachRemaining(Consumer<? super Map.Entry<K, V>> action) {
            int i, hi, mc;
            if (action == null)
                throw new NullPointerException();
            WeakHashMap<K,V> m = map;
            WeakHashMap.Entry<K,V>[] tab = m.table;
            if ((hi = fence) < 0) {
                mc = expectedModCount = m.modCount;
                hi = fence = tab.length;
            }
            else
                mc = expectedModCount;
            if (tab.length >= hi && (i = index) >= 0 &&
                (i < (index = hi) || current != null)) {
                WeakHashMap.Entry<K,V> p = current;
                current = null; // exhaust
                do {
                    if (p == null)
                        p = tab[i++];
                    else {
                        Object x = p.get();
                        V v = p.value;
                        p = p.next;
                        if (x != null) {
                            @SuppressWarnings("unchecked") K k =
                                (K) WeakHashMap.unmaskNull(x);
                            action.accept
                                (new AbstractMap.SimpleImmutableEntry<K,V>(k, v));
                        }
                    }
                } while (p != null || i < hi);
            }
            if (m.modCount != mc)
                throw new ConcurrentModificationException();
        }

        public boolean tryAdvance(Consumer<? super Map.Entry<K,V>> action) {
            int hi;
            if (action == null)
                throw new NullPointerException();
            WeakHashMap.Entry<K,V>[] tab = map.table;
            if (tab.length >= (hi = getFence()) && index >= 0) {
                while (current != null || index < hi) {
                    if (current == null)
                        current = tab[index++];
                    else {
                        Object x = current.get();
                        V v = current.value;
                        current = current.next;
                        if (x != null) {
                            @SuppressWarnings("unchecked") K k =
                                (K) WeakHashMap.unmaskNull(x);
                            action.accept
                                (new AbstractMap.SimpleImmutableEntry<K,V>(k, v));
                            if (map.modCount != expectedModCount)
                                throw new ConcurrentModificationException();
                            return true;
                        }
                    }
                }
            }
            return false;
        }

        public int characteristics() {
            return Spliterator.DISTINCT;
        }
    }

}


本文是作者自己学习过程中理解记录下来的,如果有不正确的地方,望指正,共进步!


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:98248次
    • 积分:2265
    • 等级:
    • 排名:第17536名
    • 原创:133篇
    • 转载:4篇
    • 译文:0篇
    • 评论:24条
    个人博客
    GitHub
    博客专栏