org.aspectj.util.SoftHashMap Maven / Gradle / Ivy
/* *******************************************************************
* Copyright (c) 2017 Contributors
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Eclipse Public License v 2.0
* which accompanies this distribution and is available at
* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
* ******************************************************************/package org.aspectj.util;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.util.AbstractMap;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class SoftHashMap extends AbstractMap {
private Map map;
private ReferenceQueue super V> rq = new ReferenceQueue();
public SoftHashMap() {
this.map = new HashMap<>();
}
class SpecialValue extends SoftReference {
private final K key;
SpecialValue(K k, V v) {
super(v, rq);
this.key = k;
}
}
@SuppressWarnings("unchecked")
private void processQueue() {
SpecialValue sv = null;
while ((sv = (SpecialValue)rq.poll()) != null) {
map.remove(sv.key);
}
}
@Override
public V get(Object key) {
SpecialValue ref = map.get(key);
if (ref == null) {
map.remove(key);
return null;
}
V value = ref.get();
if (value == null) {
map.remove(ref.key);
return null;
}
return value;
}
@Override
public V put(K k, V v) {
processQueue();
SpecialValue sv = new SpecialValue(k, v);
SpecialValue result = map.put(k, sv);
return (result == null ? null : result.get());
}
@Override
public java.util.Set> entrySet() {
if (map.isEmpty()) { return Collections.emptyMap().entrySet(); }
Map currentContents = new HashMap<>();
for (Map.Entry entry: map.entrySet()) {
V currentValueForEntry = entry.getValue().get();
if (currentValueForEntry != null) {
currentContents.put(entry.getKey(), currentValueForEntry);
}
}
return currentContents.entrySet();
}
@Override
public void clear() {
processQueue();
map.clear();
}
@Override
public int size() {
processQueue();
return map.size();
}
@Override
public V remove(Object k) {
processQueue();
SpecialValue ref = map.remove(k);
if (ref == null) {
return null;
}
return ref.get();
}
}