Looking through the WeakHashMap code, it seems that there is no direct way to do this, but something from this following form should work: (This code has not actually been tested, but I think it is at least on the right track, it also implements only put and get, other operations can also be implemented)
public class MyMap<K, V> { private class MyKey<K> extends WeakReference<K> { private final int hashCode; private MyKey(K k, ReferenceQueue<K> q) { super(k, q); hash = k.hashCode(); } private MyKey(K k) { super(k); hash = k.hashCode(); } @Override public int hashCode() { return hashCode; } @Override public boolean equals(Object o) { if (!(o instanceof MyKey)) { return false; } K otherKey = ((MyKey<K>) o).get(); K myKey = get(); if (otherKey != null && key != null) { return otherKey.equals(myKey); } return this == o; } } private final Map<MyKey<K>, V> map = new ConcurrentHashMap<MyKey<K>, V>(); private final ReferenceQueue<K> queue = new ReferenceQueue<K>(); public V put(K key, V val) { expungeStaleEntries(); return map.put(new MyKey<K>(key, queue), val); } public V get(K key) { expungeStaleEntries(); return map.get(new MyKey<K>(key)); } private void expungeStaleEntries() { MyKey<K> key = null; while ((key = (MyKey<K>) queue.poll()) != null) { map.remove(key); } } }
The potential incorrectness of the above code aside, another caveat is that WeakHashMap works by calling its own expungeStaleEntries() method every time you call things like put() , get() or even size() . However, the problem with this in the current scenario is that ReferenceQueue.poll() does the actual polling inside the synchronized block, so cleaning can slow down (however, it will not block if the queue is empty, so it doesnβt cancel all work on improving the speed ConcurrentHashMap ).
source share