Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
io.polaris.core.map.ReferenceMap Maven / Gradle / Ivy
package io.polaris.core.map;
import io.polaris.core.function.TernaryFunction;
import io.polaris.core.map.reference.ReferenceType;
import io.polaris.core.map.reference.ValueReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.util.AbstractMap;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;
/**
* @author Qt
* @since 1.8
*/
@SuppressWarnings({"rawtypes", "unchecked"})
public class ReferenceMap extends AbstractMap implements Map {
private final BiFunction, Reference> keyRreferenceFactory;
private final TernaryFunction, V, ReferenceQueue, ValueReference, V>> valueReferenceFactory;
private final Map, ValueReference, V>> raw;
private final ReferenceQueue keyQueue = new ReferenceQueue<>();
private final ReferenceQueue valueQueue = new ReferenceQueue<>();
public ReferenceMap(Map, ValueReference, V>> raw, ReferenceType referenceType) {
this.raw = raw;
this.valueReferenceFactory = referenceType::buildValueReference;
this.keyRreferenceFactory = referenceType::buildKeyReference;
}
public ReferenceMap(Supplier, ValueReference, V>>> supplier, ReferenceType referenceType) {
this(supplier.get(), referenceType);
}
private Reference buildKeyReference(K key) {
return keyRreferenceFactory.apply(key, keyQueue);
}
private ValueReference, V> buildValueReference(Reference key, V value) {
return valueReferenceFactory.apply(key, value, valueQueue);
}
private void processQueue() {
{
// remove by key
Reference extends K> ref;
while ((ref = keyQueue.poll()) != null) {
raw.remove(ref);
}
}
{
// remove by value
Reference extends V> ref;
while ((ref = valueQueue.poll()) != null) {
if (ref instanceof ValueReference) {
ValueReference, V> vr = (ValueReference, V>) ref;
Reference keyRef = vr.key();
raw.remove(keyRef, vr);
}
}
}
}
public int size() {
processQueue();
return raw.size();
}
public boolean isEmpty() {
processQueue();
return raw.isEmpty();
}
public boolean containsKey(Object key) {
if (key == null) {
throw new NullPointerException();
}
processQueue();
return raw.containsKey(buildKeyReference((K) key));
}
public V get(Object key) {
if (key == null) {
throw new NullPointerException();
}
processQueue();
ValueReference, V> ref = raw.get(buildKeyReference((K) key));
if (ref != null) {
return ref.value();
}
return null;
}
public V put(K key, V value) {
if (key == null) {
throw new NullPointerException();
}
if (value == null) {
throw new NullPointerException();
}
processQueue();
Reference keyRef = buildKeyReference((K) key);
ValueReference, V> ref = raw.put(keyRef, buildValueReference(keyRef, value));
if (ref != null) {
return ref.value();
}
return null;
}
public V remove(Object key) {
if (key == null) {
throw new NullPointerException();
}
processQueue();
ValueReference, V> removed = raw.remove(buildKeyReference((K) key));
if (removed == null) {
return null;
}
return removed.value();
}
public void clear() {
processQueue();
raw.clear();
}
@Override
public java.util.Set> entrySet() {
if (raw.isEmpty()) {
return Collections.emptyMap().entrySet();
}
processQueue();
if (raw.isEmpty()) {
return Collections.emptyMap().entrySet();
}
Map map = new HashMap();
for (Entry, ValueReference, V>> entry : raw.entrySet()) {
ValueReference, V> valueReference = entry.getValue();
if (valueReference == null) {
continue;
}
V value = valueReference.value();
if (value == null) {
continue;
}
K key = entry.getKey().get();
if (key == null) {
continue;
}
map.put(key, value);
}
return map.entrySet();
}
// region 代理接口默认方法
@Override
public void replaceAll(BiFunction super K, ? super V, ? extends V> function) {
processQueue();
raw.replaceAll((k, v) ->
buildValueReference(k, function.apply(k.get(), v.value()))
);
}
@Override
public V putIfAbsent(K key, V value) {
processQueue();
Reference keyRef = buildKeyReference(key);
ValueReference, V> ref = raw.putIfAbsent(keyRef, buildValueReference(keyRef, value));
return ref == null ? null : ref.value();
}
@Override
public boolean remove(Object key, Object value) {
processQueue();
Reference keyRef = buildKeyReference((K) key);
return raw.remove(keyRef, buildValueReference(keyRef, (V) value));
}
@Override
public boolean replace(K key, V oldValue, V newValue) {
processQueue();
Reference keyRef = buildKeyReference(key);
return raw.replace(keyRef, buildValueReference(keyRef, oldValue), buildValueReference(keyRef, newValue));
}
@Override
public V replace(K key, V value) {
processQueue();
Reference keyRef = buildKeyReference(key);
ValueReference, V> ref = raw.replace(keyRef, buildValueReference(keyRef, value));
return ref == null ? null : ref.value();
}
@Override
public V computeIfAbsent(K key, Function super K, ? extends V> mappingFunction) {
processQueue();
Reference keyRef = buildKeyReference(key);
ValueReference, V> ref = raw.computeIfAbsent(keyRef, (k) -> buildValueReference(k, mappingFunction.apply(k.get())));
return ref == null ? null : ref.value();
}
@Override
public V computeIfPresent(K key, BiFunction super K, ? super V, ? extends V> remappingFunction) {
processQueue();
Reference keyRef = buildKeyReference(key);
ValueReference, V> ref = raw.computeIfPresent(keyRef, (k, v) ->
buildValueReference(k, v == null ? null : remappingFunction.apply(k.get(), v.value())));
return ref == null ? null : ref.value();
}
@Override
public V compute(K key, BiFunction super K, ? super V, ? extends V> remappingFunction) {
processQueue();
Reference keyRef = buildKeyReference(key);
ValueReference, V> ref = raw.compute(keyRef, (k, v) ->
buildValueReference(k, remappingFunction.apply(k.get(), v == null ? null : v.value())));
return ref == null ? null : ref.value();
}
@Override
public V merge(K key, V value, BiFunction super V, ? super V, ? extends V> remappingFunction) {
processQueue();
Reference keyRef = buildKeyReference(key);
ValueReference, V> ref = raw.merge(keyRef, buildValueReference(keyRef, value), (v1, v2) ->
buildValueReference(keyRef, remappingFunction.apply(v1.value(), v2.value())));
return ref == null ? null : ref.value();
}
// endregion
}