WeakHashMap分析

第1部分 WeakHashMap介绍

WeakHashMap简介

WeakHashMap实现了Map接口,因此需要实现K,V,K-V三种类型的操作。
WeakHashMap跟JDK8以前的HashMap很像,没有实现红黑树结构,插入元素的时候使用的是头插法。
WeakHashMap的Key是弱键,当设为null的时候会被加入queue中,在每次访问元素的时候,都会先清理已被回收的元素。

WeakHashMap构造函数

修饰语和返回类型方法描述
publicWeakHashMap(int initialCapacity, float loadFactor)传入初始容量和加载因子
publicWeakHashMap(int initialCapacity)传入初始容量
publicWeakHashMap()默认构造函数
publicWeakHashMap(Map<? extends K, ? extends V> m)根据m构造

WeakHashMap常用API

修饰语和返回类型方法描述
intsize()元素个数
booleanisEmpty()是否为空
Vget(Object key)根据key获取value
booleancontainsKey(Object key)是否包含key
Vput(K key, V value)插入元素
voidputAll(Map<? extends K, ? extends V> m)添加m里的元素
Vremove(Object key)移除元素
voidclear()清空
booleancontainsValue(Object value)是否包含value
voidclear()清空

第2部分 WeakHashMap数据结构

WeakHashMap的继承关系

java.lang.Object
   ↳     java.util.AbstractMap<K, V>
         ↳    

public class WeakHashMap<K,V> extends AbstractMap<K,V>
    implements Map<K,V> {}

WeakHashMap的关系图
在这里插入图片描述
图1 WeakHashMap的关系图

第3部分 WeakHashMap源码解析(基于JDK-8u201)

WeakHashMap的源码跟HashMap很像,但是没有红黑树结构,而且WeakHashMap的引用为弱引用,下面的分析主要针对不同的进行分析。

内部结点Entry

private static class Entry<K,V> extends WeakReference<Object> implements Map.Entry<K,V> {
    V value;
    final int hash;
    Entry<K,V> next;

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

    @SuppressWarnings("unchecked")
    public K getKey() {
    	/*get()是祖父类中获取对象索引的方法,如果已被删除,则会返回null
    	WeakHashMap把key为null都转为NULL_KEY对象
    	*/
        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))) {
            V v1 = getValue();
            Object v2 = e.getValue();
            if (v1 == v2 || (v1 != null && v1.equals(v2)))
                return true;
        }
        return false;
    }
    public int hashCode() {
        K k = getKey();
        V v = getValue();
        return Objects.hashCode(k) ^ Objects.hashCode(v);
    }
    public String toString() {
        return getKey() + "=" + getValue();
    }
}

迭代器

private abstract class HashIterator<T> implements Iterator<T> {
    private int index;
    private Entry<K,V> entry;//下一个元素
    private Entry<K,V> lastReturned;
    private int expectedModCount = modCount;

    private Object nextKey;//下一个key
    private Object currentKey;//当前key

    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;
            }
            //确保元素还没被删,如果被删,拿到的是null
            nextKey = e.get(); // hold on to key in strong ref
            if (nextKey == null)
                entry = entry.next;
        }
        return true;
    }
	
    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;
    }

}
//后面几个类都是实现next的具体返回类型
private class ValueIterator extends HashIterator<V> {
    public V next() {
        return nextEntry().value;
    }
}

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

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

三个集合

//KeySet基本都是调用外部类WeakHashMap的方法
private class KeySet extends AbstractSet<K> {
    public Iterator<K> iterator() {
        return new KeyIterator();
    }
    public int size() {
        return WeakHashMap.this.size();
    }
    public boolean contains(Object o) {
        return containsKey(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);
    }
}

private class Values extends AbstractCollection<V> {
    public Iterator<V> iterator() {
        return new ValueIterator();
    }

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

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

private class EntrySet extends AbstractSet<Map.Entry<K,V>> {
    public Iterator<Map.Entry<K,V>> iterator() {
        return new EntryIterator();
    }
    public boolean contains(Object o) {
        if (!(o instanceof Map.Entry))
            return false;
        Map.Entry<?,?> e = (Map.Entry<?,?>)o;
        //根据key去获取对象并判断是否相等
        Entry<K,V> candidate = getEntry(e.getKey());
        return candidate != null && candidate.equals(e);
    }
    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());
        //注意,使用的不是WeakHashMap里的Entry类型创建,也就是键不是弱键
        for (Map.Entry<K,V> e : this)
            list.add(new AbstractMap.SimpleEntry<>(e));
        return list;
    }
    public Object[] toArray() {
    	//调用List的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);
    }
}

可分割迭代器

WeakHashMap跟HashMap的可分割迭代器差距也不大,只是由于其键为弱键,可能已经被回收,所以在遍历的过程,无论是否处理单个元素,都在外围采用循环结构。

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

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

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

WeakHashMap

public class WeakHashMap<K,V> extends AbstractMap<K,V>
    implements Map<K,V> {
	
    private static final int DEFAULT_INITIAL_CAPACITY = 16;//默认容量16
    private static final int MAXIMUM_CAPACITY = 1 << 30;//最大容量2^30
    private static final float DEFAULT_LOAD_FACTOR = 0.75f;//默认加载因子0.75
    
    Entry<K,V>[] table;//表
    private int size;//元素个数
    private int threshold;//阈值
    private final float loadFactor;//加载因子
    private final ReferenceQueue<Object> queue = new ReferenceQueue<>();//被回收键存放的队列
    int modCount;

    @SuppressWarnings("unchecked")
    private Entry<K,V>[] newTable(int n) {
        return (Entry<K,V>[]) new Entry<?,?>[n];
    }

    public WeakHashMap(int initialCapacity, float loadFactor) {
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Initial Capacity: "+
                                               initialCapacity);
        if (initialCapacity > MAXIMUM_CAPACITY)
            initialCapacity = MAXIMUM_CAPACITY;
		//isNaN是is not a num的意思,例如3/0
        if (loadFactor <= 0 || Float.isNaN(loadFactor))
            throw new IllegalArgumentException("Illegal Load factor: "+
                                               loadFactor);
        int capacity = 1;
        //找到第一个大于等于initialCapacity的2的幂
        while (capacity < initialCapacity)
            capacity <<= 1;
        table = newTable(capacity);
        this.loadFactor = loadFactor;
        threshold = (int)(capacity * loadFactor);//计算阈值
    }

    public WeakHashMap(int initialCapacity) {
        this(initialCapacity, DEFAULT_LOAD_FACTOR);
    }

    public WeakHashMap() {
        this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR);
    }

    public WeakHashMap(Map<? extends K, ? extends V> m) {
        this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1,
                DEFAULT_INITIAL_CAPACITY),
             DEFAULT_LOAD_FACTOR);
        putAll(m);
    }
	//讲key为null的都用此对象代替
    private static final Object NULL_KEY = new Object();
    private static Object maskNull(Object key) {
        return (key == null) ? NULL_KEY : key;
    }
	//转回来
    static Object unmaskNull(Object key) {
        return (key == NULL_KEY) ? null : key;
    }
	
    private static boolean eq(Object x, Object y) {
        return x == y || x.equals(y);
    }
	//求哈希值
    final int hash(Object k) {
        int h = k.hashCode();
        h ^= (h >>> 20) ^ (h >>> 12);
        return h ^ (h >>> 7) ^ (h >>> 4);
    }
	//求桶索引
    private static int indexFor(int h, int length) {
        return h & (length-1);
    }
	//清除已被回收的元素
    private void expungeStaleEntries() {
    	//遍历queue,queue里保存的是已经被移除的key
        for (Object x; (x = queue.poll()) != null; ) {
            synchronized (queue) {
                @SuppressWarnings("unchecked")
                    Entry<K,V> e = (Entry<K,V>) x;
                int i = indexFor(e.hash, table.length);

                Entry<K,V> prev = table[i];
                Entry<K,V> p = prev;
                //往后遍历,并保存前驱
                while (p != null) {
                    Entry<K,V> next = p.next;
                    //找到了,并移除
                    if (p == e) {
                        if (prev == e)
                            table[i] = next;
                        else
                            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;
                }
            }
        }
    }
	//获取表格前先清除无用数据
    private Entry<K,V>[] getTable() {
        expungeStaleEntries();
        return table;
    }
    public int size() {
        if (size == 0)
            return 0;
        expungeStaleEntries();
        return size;
    }
    public boolean isEmpty() {
        return size() == 0;
    }

    public V get(Object key) {
    	//先转换key
        Object k = maskNull(key);
        int h = hash(k);
        //该函数会清理已回收元素
        Entry<K,V>[] tab = getTable();
        int index = indexFor(h, tab.length);
        Entry<K,V> e = tab[index];
        //遍历索引为index的桶
        while (e != null) {
            if (e.hash == h && eq(k, e.get()))
                return e.value;
            e = e.next;
        }
        return null;
    }

    public boolean containsKey(Object key) {
        return getEntry(key) != null;
    }
	//从该方法可以看出,其实上面的get(Object key)可以调用此方法,再返回e==null?null:e.value
    Entry<K,V> getEntry(Object key) {
        Object k = maskNull(key);
        int h = hash(k);
        Entry<K,V>[] tab = getTable();
        int index = indexFor(h, tab.length);
        Entry<K,V> e = tab[index];
        while (e != null && !(e.hash == h && eq(k, e.get())))
            e = e.next;
        return e;
    }

    public V put(K key, V value) {
        Object k = maskNull(key);
        int h = hash(k);
        Entry<K,V>[] tab = getTable();
        int i = indexFor(h, tab.length);

        for (Entry<K,V> e = tab[i]; e != null; e = e.next) {
            if (h == e.hash && eq(k, e.get())) {
                V oldValue = e.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)
            resize(tab.length * 2);//扩容为两倍
        return null;
    }

    void resize(int newCapacity) {
        Entry<K,V>[] oldTable = getTable();
        int oldCapacity = oldTable.length;
        if (oldCapacity == MAXIMUM_CAPACITY) {
            threshold = Integer.MAX_VALUE;
            return;
        }

        Entry<K,V>[] newTable = newTable(newCapacity);
        //将元素都添加进newTable
        transfer(oldTable, newTable);
        table = newTable;

        if (size >= threshold / 2) {
            threshold = (int)(newCapacity * loadFactor);
        } else {
            expungeStaleEntries();
            transfer(newTable, oldTable);
            table = oldTable;
        }
    }

    private void transfer(Entry<K,V>[] src, Entry<K,V>[] dest) {
        //遍历桶
        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 {
                    int i = indexFor(e.hash, dest.length);
                    e.next = dest[i];
                    dest[i] = e;
                }
                e = next;
            }
        }
    }

    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;
            int newCapacity = table.length;
            //求大于等于targetCapacity的2次幂
            while (newCapacity < targetCapacity)
                newCapacity <<= 1;
            //扩容
            if (newCapacity > table.length)
                resize(newCapacity);
        }
		//添加元素
        for (Map.Entry<? extends K, ? extends V> e : m.entrySet())
            put(e.getKey(), e.getValue());
    }

    public V remove(Object key) {
        Object k = maskNull(key);
        int h = hash(k);
        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)
                    tab[i] = next;
                else
                    prev.next = next;
                return e.value;
            }
            prev = e;
            e = next;
        }

        return null;
    }
	//移除entry
    boolean removeMapping(Object o) {
        if (!(o instanceof Map.Entry))
            return false;
        Entry<K,V>[] tab = getTable();
        Map.Entry<?,?> entry = (Map.Entry<?,?>)o;
        Object k = maskNull(entry.getKey());
        int h = hash(k);
        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;
    }

    public void clear() {
    	//清空队列
        while (queue.poll() != null);

        modCount++;
        Arrays.fill(table, null);//置为null
        size = 0;
		//再次清空队列
        while (queue.poll() != null);
    }

    public boolean containsValue(Object value) {
        if (value==null)
            return 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 (value.equals(e.value))
                    return true;
        return false;
    }

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

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

    public Set<K> keySet() {
        Set<K> ks = keySet;
        if (ks == null) {
            ks = new KeySet();
            keySet = ks;
        }
        return ks;
    }
    
	public Collection<V> values() {
    	Collection<V> vs = values;
    	if (vs == null) {
        	vs = new Values();
        	values = vs;
    	}
    	return vs;
	}

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

    @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.accept((K)WeakHashMap.unmaskNull(key), entry.value);
                }
                entry = entry.next;

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

    @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) {
                    entry.value = function.apply((K)WeakHashMap.unmaskNull(key), entry.value);
                }
                entry = entry.next;

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

看完上面的源码,也许读者会很疑惑,被回收的键是什么时候,或者通过什么方式被加进queue的。在创建entry时,调用了

 Entry(Object key, V value,ReferenceQueue<Object> queue,
              int hash, Entry<K,V> next) {
              
            super(key, queue);
        }

这个super(key, queue)最终通过其父类Reference,将key对象的索引注册到这个队列中,当key被回收时,垃圾回收器会执行以下操作:

 /**
     * Adds this reference object to the queue with which it is registered,
     * if any.
     *
     * <p> This method is invoked only by Java code; when the garbage collector
     * enqueues references it does so directly, without invoking this method.
     *
     * @return   <code>true</code> if this reference object was successfully
     *           enqueued; <code>false</code> if it was already enqueued or if
     *           it was not registered with a queue when it was created
     */
    public boolean enqueue() {
        return this.queue.enqueue(this);
    }

注释上的意思是,垃圾回收器回收时,会将已注册的索引添加到queue中,但是实际上,垃圾回收器并不会调用这个方法,而是直接将其加入队列。

这个方法没被调用,却还写上去,就是为了帮助人理解,写JDK的大神还是很细心的嘛。

第4部分 WeakHashMap使用示例

由于WeakHashMap和HashMap还是很像的,因此示例主要演示其不同点,也就是弱键。

public class Test5 {
	public static void main( String[]args) throws InterruptedException {
		
		Integer key=new Integer(6);//强引用
		
		WeakHashMap<Integer, Integer> weakHashMap1=new WeakHashMap<>();
		weakHashMap1.put(key, new Integer(12));
		for(int i=0;i<5;i++) {
			weakHashMap1.put(new Integer(i), new Integer(2*i));//弱引用
		}
		//通知垃圾回收器回收
		System.gc();
		Thread.sleep(200);
		System.out.println("weakHashMap1:"+weakHashMap1.entrySet());
		
		WeakHashMap<Integer, Integer> weakHashMap2=new WeakHashMap<>();
		for(int i=0;i<5;i++) {
			weakHashMap2.put(i, 2*i);//方法区的引用
		}
		System.gc();
		Thread.sleep(200);
		System.out.println("weakHashMap2:"+weakHashMap2.entrySet());

		HashMap<Integer, Integer> hashMap=new HashMap<>();
		for(int i=0;i<5;i++) {
			hashMap.put(new Integer(i), new Integer(2*i));
		}
		System.gc();
		Thread.sleep(200);
		System.out.println("hashMap:"+hashMap.entrySet());
	}
}

输出

weakHashMap1:[6=12]
weakHashMap2:[4=8, 3=6, 2=4, 1=2, 0=0]
hashMap:[0=0, 1=2, 2=4, 3=6, 4=8]

从上面例子中可以看出,由于new创建,但是没有对象保持其索引,是不可达的,当通知垃圾回收器回收的时候,就会被回收掉。但是使用方法区的引用,强引用或者使用HashMap是不会被回收的。

由于这个特性WeakHashMap不可以当主缓存使用,一般被用作二级缓存。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值