WeakHashMap分析

  • 第1部分 WeakHashMap介绍
  • 第2部分 WeakHashMap数据结构
  • 第3部分 WeakHashMap源码解析(基于JDK-8u201)
    • 内部结点Entry
    • 迭代器
    • 三个集合
    • 可分割迭代器
    • WeakHashMap
  • 第4部分 WeakHashMap使用示例

第1部分 WeakHashMap介绍

WeakHashMap简介

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

WeakHashMap构造函数

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

WeakHashMap常用API

修饰语和返回类型 方法 描述
int size() 元素个数
boolean isEmpty() 是否为空
V get(Object key) 根据key获取value
boolean containsKey(Object key) 是否包含key
V put(K key, V value) 插入元素
void putAll(Map<? extends K, ? extends V> m) 添加m里的元素
V remove(Object key) 移除元素
void clear() 清空
boolean containsValue(Object value) 是否包含value
void clear() 清空

第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()是祖父类中获取对象索引的方法,如果已被删除,则会返回nullWeakHashMap把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;//下一个keyprivate Object currentKey;//当前keyHashIterator() {//索引初始化为最后的桶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;}//确保元素还没被删,如果被删,拿到的是nullnextKey = e.get(); // hold on to key in strong refif (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;}elsereturn 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 nodeint index;             // current index, modified on advance/splitint fence;             // -1 until first use; then one past last indexint est;               // size estimateint expectedModCount;  // for comodification checksWeakHashMapSpliterator(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 useint 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 initreturn (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;}elsemc = expectedModCount;//有元素    if (tab.length >= hi && (i = index) >= 0 &&(i < (index = hi) || current != null)) {WeakHashMap.Entry<K,V> p = current;current = null; // exhaustdo {//从前往后遍历桶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;}elsemc = expectedModCount;if (tab.length >= hi && (i = index) >= 0 &&(i < (index = hi) || current != null)) {WeakHashMap.Entry<K,V> p = current;current = null; // exhaustdo {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;}elsemc = expectedModCount;if (tab.length >= hi && (i = index) >= 0 &&(i < (index = hi) || current != null)) {WeakHashMap.Entry<K,V> p = current;current = null; // exhaustdo {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;//默认容量16private static final int MAXIMUM_CAPACITY = 1 << 30;//最大容量2^30private static final float DEFAULT_LOAD_FACTOR = 0.75f;//默认加载因子0.75Entry<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/0if (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里保存的是已经被移除的keyfor (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;elseprev.next = next;// Must not null out e.next;// stale entries may be in use by a HashIteratore.value = null; // Help GCsize--;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) {//先转换keyObject 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.valueEntry<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);//将元素都添加进newTabletransfer(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 GCe.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;elseprev.next = next;return e.value;}prev = e;e = next;}return null;}//移除entryboolean 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;elseprev.next = next;return true;}prev = e;e = next;}return false;}public void clear() {//清空队列while (queue.poll() != null);modCount++;Arrays.fill(table, null);//置为nullsize = 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")@Overridepublic 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")@Overridepublic 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不可以当主缓存使用,一般被用作二级缓存。

WeakHashMap分析相关推荐

  1. WeakHashMap源码分析

    前言:WeakHashMap可能平时使用的频率并不高,但是你可能听过WeakHashMap会进行自动回收吧,下面就对其原理进行分析. 注:本文jdk源码版本为jdk1.8.0_172 1.WeakHa ...

  2. linux java内存分析_Java内存分析利器MAT使用详解

    这是一篇阅读MAT helper的笔记.Heap dump是Java进程在特定时间的一个内存快照.通常在触发heap dump之前会进行一次full gc,这样dump出来的内容就包含的是被gc后的对 ...

  3. 使用Memory Analyzer tool(MAT)分析内存泄漏(一)

    使用Memory Analyzer tool(MAT)分析内存泄漏(一) (2010年05月21日) 发表于 Java博客 前言的前言 :本文是自 2005 年 8 月以来,首次在一个月之内发布三篇文 ...

  4. java集合框架07——Map架构与源代码分析

    前几节我们对Collection以及Collection中的List部分进行了分析,Collection中还有个Set,因为Set是基于Map实现的,所以这里我们先分析Map,后面章节再继续学习Set ...

  5. 内存分析工具MAT的使用

    原文链接:http://www.jianshu.com/p/d8e247b1e7b2 MAT简介 MAT(Memory Analyzer Tool),一个基于Eclipse的内存分析工具,是一个快速. ...

  6. spring源码分析之spring-core总结篇

    1.spring-core概览 spring-core是spring框架的基石,它为spring框架提供了基础的支持. spring-core从源码上看,分为6个package,分别是asm,cgli ...

  7. spring remoting源码分析--Hessian分析

    1. Caucho 1.1 概况 spring-remoting代码的情况如下: 本节近分析caucho模块. 1.2 分类 其中以hession为例,Hessian远程服务调用过程: Hessian ...

  8. Java 动态代理机制分析及扩展--转

    http://www.ibm.com/developerworks/cn/java/j-lo-proxy1/#icomments http://www.ibm.com/developerworks/c ...

  9. Java 动态代理机制分析及扩展,第 1 部分

    引言 Java 动态代理机制的出现,使得 Java 开发人员不用手工编写代理类,只要简单地指定一组接口及委托类对象,便能动态地获得代理类.代理类会负责将所有的方法调用分派到委托对象上反射执行,在分派执 ...

最新文章

  1. LAMP--Apache 禁止指定 user_agent
  2. 【人物】徐磊:对用户驯养,只需要让用户记得你会给肉
  3. Mongodb实现多表join
  4. react(95)--外部定义变量
  5. JS之字符串截取函数substr
  6. Redis:16---常用功能之(慢查询日志)
  7. 【Java】判断某值是否在数组中,使用Arrays类
  8. Creating and Interning Symbols
  9. matplotlib图表涉及中乱码问题
  10. JAVA POJ3233—矩阵幂序列问题
  11. c语言中calc是什么函数,CSS 3 中的计算函数 calc() 有啥用?
  12. 计算机软件实习每日学习打卡(4)20201206
  13. 基于stm32/单片机/DSP/Java的毕业设计 课程设计
  14. oracle修改查询结果,Oracle使用查询结果更新表的方法
  15. win11共享打印机无法连接怎么办
  16. DNS服务(域名系统、过程、bind、配置文件、查看本设备dns)
  17. VS2019 KEY
  18. 家庭玩游戏配置哪种计算机,玩游戏用什么系统?Win10专业版和Win10家庭版玩游戏的区别...
  19. oeasy教您玩转vim - 89 - # 高亮细节Highlight
  20. 屏保文件scr文件制作方法

热门文章

  1. android设备登录是什么手机_手机能当U盾用,谷歌要让安卓比iOS更安全?
  2. 苹果7升级系统后无服务器,iPhone7显示无服务怎么办 iPhone7显示无服务解决办法...
  3. 苹果录屏功能在哪?教你轻松开启iPhone录屏
  4. excel 信息批量转PPT
  5. python多线程并发测试
  6. matlab如何旋转图例
  7. 计算机网络-网络层总结
  8. python爬虫——模拟登陆
  9. 商品SPU与SKU概念区别
  10. 不拆CPU风扇也能上油