com.firefly.utils.collection.AbstractConcurrentAutomaticClearMap Maven / Gradle / Ivy
package com.firefly.utils.collection;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
abstract public class AbstractConcurrentAutomaticClearMap implements ConcurrentAutomaticClearMap, ConcurrentMap {
protected Map> map = new ConcurrentHashMap<>();
protected ReferenceQueue refQueue = new ReferenceQueue<>();
public void clearAllInvalidEntry() {
Reference extends V> ref;
while ((ref = refQueue.poll()) != null) {
clearInvalidEntry(ref);
}
}
abstract protected void clearInvalidEntry(Reference extends V> ref);
abstract protected Reference createRefence(K key, V value);
@Override
public int size() {
clearAllInvalidEntry();
return map.size();
}
@Override
public boolean isEmpty() {
clearAllInvalidEntry();
return map.isEmpty();
}
@Override
public boolean containsKey(Object key) {
return map.containsKey(key);
}
@Override
public V get(Object key) {
Reference ref = map.get(key);
if (ref == null)
return null;
V value = ref.get();
if (value == null) {
clearInvalidEntry(ref);
return null;
} else {
return value;
}
}
@Override
public V put(K key, V value) {
clearAllInvalidEntry();
Reference ref = map.put(key, createRefence(key, value));
return ref != null ? ref.get() : null;
}
@Override
public V putIfAbsent(K key, V value) {
clearAllInvalidEntry();
Reference ref = map.putIfAbsent(key, createRefence(key, value));
return ref != null ? ref.get() : null;
}
@Override
public void putAll(Map extends K, ? extends V> m) {
clearAllInvalidEntry();
for (Map.Entry extends K, ? extends V> entry : m.entrySet()) {
put(entry.getKey(), entry.getValue());
}
}
@Override
public V replace(K key, V value) {
Reference ref = map.replace(key, createRefence(key, value));
return ref != null ? ref.get() : null;
}
@Override
public boolean replace(K key, V oldValue, V newValue) {
return map.replace(key, createRefence(key, oldValue), createRefence(key, newValue));
}
@Override
public V remove(Object key) {
clearAllInvalidEntry();
Reference ref = map.remove(key);
return ref != null ? ref.get() : null;
}
@SuppressWarnings("unchecked")
@Override
public boolean remove(Object key, Object value) {
clearAllInvalidEntry();
return map.remove(key, createRefence((K) key, (V) value));
}
@Override
public void clear() {
clearAllInvalidEntry();
map.clear();
}
@Override
public Set keySet() {
return map.keySet();
}
@Override
public Collection values() {
Collection collection = new LinkedList<>();
for (Map.Entry entry : entrySet()) {
collection.add(entry.getValue());
}
return collection;
}
@Override
public boolean containsValue(Object value) {
for (V v : values()) {
if (v != null && v.equals(value)) {
return true;
}
}
return false;
}
@Override
public Set> entrySet() {
Set> set = new HashSet<>();
for (Map.Entry> entry : map.entrySet()) {
Reference ref = entry.getValue();
V value = ref.get();
if (value == null) {
clearInvalidEntry(ref);
} else {
set.add(new MapEntryImpl(entry.getKey(), value));
}
}
return set;
}
protected class MapEntryImpl implements Map.Entry {
K key;
V value;
public MapEntryImpl(K key, V value) {
this.key = key;
this.value = value;
}
@Override
public K getKey() {
return key;
}
@Override
public V getValue() {
return value;
}
@Override
public V setValue(V value) {
this.value = value;
return value;
}
@Override
public String toString() {
return "MapEntry [key=" + key + ", value=" + value + "]";
}
}
}