package sun.awt;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.*;
class WeakIdentityHashMap<K, V> implements Map<K, V> {
private final Map<WeakKey<K>, V> map;
private final transient ReferenceQueue<K> queue = new ReferenceQueue<K>();
public WeakIdentityHashMap() {
map = new HashMap<>(16);
}
public WeakIdentityHashMap(int initialSize) {
map = new HashMap<>(initialSize);
}
private Map<WeakKey<K>, V> getMap() {
for(Reference<? extends K> ref; (ref = this.queue.poll()) != null;) {
map.remove(ref);
}
return map;
}
@Override
public int size() {
return getMap().size();
}
@Override
public boolean isEmpty() {
return getMap().isEmpty();
}
@Override
public boolean containsKey(Object key) {
return getMap().containsKey(new WeakKey<>(key, null));
}
@Override
public boolean containsValue(Object value) {
return getMap().containsValue(value);
}
@Override
public V get(Object key) {
return getMap().get(new WeakKey<>(key, null));
}
@Override
public V put(K key, V value) {
return getMap().put(new WeakKey<K>(key, queue), value);
}
@Override
public V remove(Object key) {
return getMap().remove(new WeakKey<>(key, null));
}
@Override
public void putAll(Map<? extends K, ? extends V> m) {
for (Entry<? extends K, ? extends V> entry : m.entrySet()) {
put(entry.getKey(), entry.getValue());
}
}
@Override
public void clear() {
getMap().clear();
}
@Override
public Set<K> keySet() {
return new AbstractSet<K>() {
@Override
public Iterator<K> iterator() {
return new Iterator<K>() {
private K next;
Iterator<WeakKey<K>> iterator = getMap().keySet().iterator();
@Override
public boolean hasNext() {
while (iterator.hasNext()) {
if ((next = iterator.next().get()) != null) {
return true;
}
}
return false;
}
@Override
public K next() {
if(next == null && !hasNext()) {
throw new NoSuchElementException();
}
K ret = next;
next = null;
return ret;
}
};
}
@Override
public int size() {
return getMap().keySet().size();
}
};
}
@Override
public Collection<V> values() {
return getMap().values();
}
@Override
public Set<Entry<K, V>> entrySet() {
return new AbstractSet<Entry<K, V>>() {
@Override
public Iterator<Entry<K, V>> iterator() {
final Iterator<Entry<WeakKey<K>, V>> iterator = getMap().entrySet().iterator();
return new Iterator<Entry<K, V>>() {
@Override
public boolean hasNext() {
return iterator.hasNext();
}
@Override
public Entry<K, V> next() {
return new Entry<K, V>() {
Entry<WeakKey<K>, V> entry = iterator.next();
@Override
public K getKey() {
return entry.getKey().get();
}
@Override
public V getValue() {
return entry.getValue();
}
@Override
public V setValue(V value) {
return null;
}
};
}
};
}
@Override
public int size() {
return getMap().entrySet().size();
}
};
}
private static class WeakKey<K> extends WeakReference<K> {
private final int hash;
WeakKey(K key, ReferenceQueue <K> q) {
super(key, q);
hash = System.identityHashCode(key);
}
@Override
public boolean equals(Object o) {
if(this == o) {
return true;
} else if( o instanceof WeakKey ) {
return get() == ((WeakKey)o).get();
} else {
return false;
}
}
@Override
public int hashCode() {
return hash;
}
}
}