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

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

There is a newer version: 3.2.1
Show newest version
package io.polaris.core.map;

import io.polaris.core.map.reference.ReferenceType;

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 KeyReferenceMap extends AbstractMap implements Map {

	private final BiFunction, Reference> referenceFactory;
	private final Map, V> raw;
	private final ReferenceQueue queue = new ReferenceQueue<>();

	public KeyReferenceMap(Map, V> raw, BiFunction, Reference> referenceFactory) {
		this.raw = raw;
		this.referenceFactory = referenceFactory;
	}

	public KeyReferenceMap(Map, V> raw, ReferenceType referenceType) {
		this.raw = raw;
		this.referenceFactory = referenceType::buildKeyReference;
	}

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


	private Reference buildKeyReference(K key) {
		return referenceFactory.apply(key, queue);
	}

	private void processQueue() {
		Reference ref;
		while ((ref = queue.poll()) != null) {
			raw.remove(ref);
		}
	}

	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();
		return raw.get(buildKeyReference((K) key));
	}

	public V put(K key, V value) {
		if (key == null) {
			throw new NullPointerException();
		}
		if (value == null) {
			throw new NullPointerException();
		}
		processQueue();
		return raw.put(buildKeyReference((K) key), value);
	}

	public V remove(Object key) {
		if (key == null) {
			throw new NullPointerException();
		}
		processQueue();
		return raw.remove(buildKeyReference((K) key));
	}

	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, V> entry : raw.entrySet()) {
			V value = entry.getValue();
			if (value != null) {
				K key = entry.getKey().get();
				if (key != null) {
					map.put(key, value);
				}
			}
		}
		return map.entrySet();
	}

	// region 代理接口默认方法

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

	@Override
	public V putIfAbsent(K key, V value) {
		processQueue();
		Reference keyRef = buildKeyReference(key);
		return raw.putIfAbsent(keyRef, value);
	}

	@Override
	public boolean remove(Object key, Object value) {
		processQueue();
		Reference keyRef = buildKeyReference((K) key);
		return raw.remove(keyRef, value);
	}

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

	@Override
	public V replace(K key, V value) {
		processQueue();
		Reference keyRef = buildKeyReference(key);
		return raw.replace(keyRef, value);
	}

	@Override
	public V computeIfAbsent(K key, Function mappingFunction) {
		processQueue();
		Reference keyRef = buildKeyReference(key);
		return raw.computeIfAbsent(keyRef, (k) -> mappingFunction.apply(k.get()));
	}

	@Override
	public V computeIfPresent(K key, BiFunction remappingFunction) {
		processQueue();
		Reference keyRef = buildKeyReference(key);
		return raw.computeIfPresent(keyRef, (k, v) -> remappingFunction.apply(k.get(), v));
	}

	@Override
	public V compute(K key, BiFunction remappingFunction) {
		processQueue();
		Reference keyRef = buildKeyReference(key);
		return raw.compute(keyRef, (k, v) -> remappingFunction.apply(k.get(), v));
	}

	@Override
	public V merge(K key, V value, BiFunction remappingFunction) {
		processQueue();
		Reference keyRef = buildKeyReference(key);
		return raw.merge(keyRef, value, (v1, v2) -> remappingFunction.apply(v1, v2));
	}

	// endregion

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy