All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.polaris.core.map.ValueReferenceMap Maven / Gradle / Ivy

There is a newer version: 3.2.1
Show newest version
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 ValueReferenceMap extends AbstractMap implements Map {

	private final TernaryFunction, ValueReference> referenceFactory;
	private final Map> raw;
	private final ReferenceQueue queue = new ReferenceQueue<>();

	public ValueReferenceMap(Map> raw, TernaryFunction, ValueReference> referenceFactory) {
		this.raw = raw;
		this.referenceFactory = referenceFactory;
	}

	public ValueReferenceMap(Map> raw, ReferenceType referenceType) {
		this.raw = raw;
		this.referenceFactory = referenceType::buildValueReference;
	}

	public ValueReferenceMap(Supplier>> supplier, ReferenceType referenceType) {
		this(supplier.get(), referenceType);
	}


	private ValueReference buildValueReference(K key, V value) {
		return referenceFactory.apply(key, value, queue);
	}

	private void processQueue() {
		Reference ref;
		while ((ref = queue.poll()) != null) {
			if (ref instanceof ValueReference) {
				ValueReference vr = (ValueReference) ref;
				raw.remove(vr.key(),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(key);
	}

	public V get(Object key) {
		if (key == null) {
			throw new NullPointerException();
		}
		processQueue();
		ValueReference ref = raw.get(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();
		ValueReference ref = raw.put(key, buildValueReference(key, value));
		if (ref != null) {
			return ref.value();
		}
		return null;
	}

	public V remove(Object key) {
		if (key == null) {
			throw new NullPointerException();
		}
		processQueue();
		ValueReference removed = raw.remove(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 (Map.Entry> entry : raw.entrySet()) {
			V value = entry.getValue().value();
			if (value != null) {
				map.put(entry.getKey(), value);
			}
		}
		return map.entrySet();
	}

	// region 代理接口默认方法

	@Override
	public void replaceAll(BiFunction function) {
		processQueue();
		raw.replaceAll((k, v) -> buildValueReference(k, function.apply(k, v.value())));
	}

	@Override
	public V putIfAbsent(K key, V value) {
		processQueue();
		ValueReference ref = raw.putIfAbsent(key, buildValueReference(key, value));
		return ref == null ? null : ref.value();
	}

	@Override
	public boolean remove(Object key, Object value) {
		processQueue();
		return raw.remove(key, buildValueReference((K) key, (V) value));
	}

	@Override
	public boolean replace(K key, V oldValue, V newValue) {
		processQueue();
		return raw.replace(key, buildValueReference(key, oldValue), buildValueReference(key, newValue));
	}

	@Override
	public V replace(K key, V value) {
		processQueue();
		ValueReference ref = raw.replace(key, buildValueReference(key, value));
		return ref == null ? null : ref.value();
	}

	@Override
	public V computeIfAbsent(K key, Function mappingFunction) {
		processQueue();
		ValueReference ref = raw.computeIfAbsent(key, (k) -> buildValueReference(k, mappingFunction.apply(k)));
		return ref == null ? null : ref.value();
	}

	@Override
	public V computeIfPresent(K key, BiFunction remappingFunction) {
		processQueue();
		ValueReference ref = raw.computeIfPresent(key, (k, v) ->
			buildValueReference(k, v == null ? null : remappingFunction.apply(k, v.value())));
		return ref == null ? null : ref.value();
	}

	@Override
	public V compute(K key, BiFunction remappingFunction) {
		processQueue();
		ValueReference ref = raw.compute(key, (k, v) ->
			buildValueReference(k, remappingFunction.apply(k, v == null ? null : v.value())));
		return ref == null ? null : ref.value();
	}

	@Override
	public V merge(K key, V value, BiFunction remappingFunction) {
		processQueue();
		ValueReference ref = raw.merge(key, buildValueReference(key, value), (v1, v2) ->
			buildValueReference(key, remappingFunction.apply(v1.value(), v2.value())));
		return ref == null ? null : ref.value();
	}

	// endregion

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy