org.codefilarete.tool.collection.IdentityMap Maven / Gradle / Ivy
package org.codefilarete.tool.collection;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
import java.util.function.Supplier;
/**
* Storage of key-value pairs based on key {@link System#identityHashCode} to avoid loss of bean in classical
* {@link Map} : because those are based on instance hashCode, beans can't be retrieved due to some hashCode change
* when computation is based on incompletely filled attributes, such as collection.
*
* It does not implement {@link Map} because it is mainly used as a marking name instead of the anonymous Map class
* which only instantiation brings the implementation : by this name the developer clearly says its intention (and
* should add a comment why such a Map is required in its algorithm ;) ).
* It could also have been replaced by {@link java.util.IdentityHashMap} (or use it internally) but, first it would
* have broken initial need, and overall one have to know that {@link java.util.IdentityHashMap} compares keys on their
* {@link System#identityHashCode} but also its values which, beyond being not really intuitive, might not be required
* by production code, and brings some difficulties in tests (because even same Strings are different with '==').
*
* @param key type
* @param value type
*/
public class IdentityMap {
private final Map delegate;
public IdentityMap() {
this.delegate = new HashMap<>();
}
public IdentityMap(int capacity) {
this.delegate = new HashMap<>(capacity);
}
protected int hash(K key) {
return System.identityHashCode(key);
}
public V put(K key, V value) {
return this.delegate.put(hash(key), value);
}
public V get(K key) {
return this.delegate.get(hash(key));
}
public boolean containsKey(K key) {
return delegate.containsKey(hash(key));
}
public V putIfAbsent(K key, V value) {
return delegate.putIfAbsent(hash(key), value);
}
public V putIfAbsent(K key, Supplier value) {
return delegate.putIfAbsent(hash(key), value.get());
}
public V computeIfAbsent(K key, Function super K, ? extends V> mappingFunction) {
return delegate.computeIfAbsent(hash(key), k -> mappingFunction.apply(key));
}
public Collection values() {
return delegate.values();
}
public V remove(K key) {
return this.delegate.remove(hash(key));
}
public void clear() {
this.delegate.clear();
}
public int size() {
return this.delegate.size();
}
/**
* Exposes internal storage, made for testing purpose, not expected to be used in production
* @return internal storage
*/
public Map getDelegate() {
return delegate;
}
/**
* Implemented for easier debug
*
* @return delegate's toString()
*/
@Override
public String toString() {
return delegate.toString();
}
}