Skip to content

Instantly share code, notes, and snippets.

@DarkSeraphim
Last active August 29, 2015 14:02
Show Gist options
  • Save DarkSeraphim/dce060e6686c22401f8f to your computer and use it in GitHub Desktop.
Save DarkSeraphim/dce060e6686c22401f8f to your computer and use it in GitHub Desktop.
Map with multiple keys to the same value, strict implementation
package net.darkseraphim.dungeons.util;
import org.apache.commons.lang.Validate;
import java.util.HashMap;
import java.util.Map;
/**
* @Author DarkSeraphim
*/
public class AmirMap<K, L, V>
{
Map<K, L> kl = new HashMap<K, L>();
Map<L, K> lk = new HashMap<L, K>();
Map<K, V> kv = new HashMap<K, V>();
Map<L, V> lv = new HashMap<L, V>();
private final Class<K> k;
private final Class<L> l;
private AmirMap(Class<K> k, Class<L> l)
{
this.k = k;
this.l = l;
}
public V get(Object key)
{
Validate.notNull(key, "null keys not supported");
if(key.getClass().isAssignableFrom(this.k))
return this.getK((K) key);
else if(key.getClass().isAssignableFrom(this.l))
return this.getL((L) key);
throw new ClassCastException(String.format("Cannot cast %s to %s nor %s", key.getClass().toString(), this.k.toString(), this.l.toString()));
}
private V getK(K key)
{
return this.kv.get(key);
}
private V getL(L key)
{
return this.lv.get(key);
}
public V put(K key, L key2, V val)
{
V a = this.kv.put(key, val);
V b = this.lv.put(key2, val);
if (a != b)
throw new IllegalStateException("Contract violated");
return a;
}
public V remove(Object key)
{
Validate.notNull(key, "null keys not supported");
if(key.getClass().isAssignableFrom(this.k))
return this.removeK((K) key);
else if(key.getClass().isAssignableFrom(this.l))
return this.removeL((L) key);
throw new ClassCastException(String.format("Cannot cast %s to %s nor %s", key.getClass().toString(), this.k.toString(), this.l.toString()));
}
private V removeK(K key)
{
L partner = this.kl.get(key);
if (partner == null)
throw new IllegalStateException("Contract violated");
V a = this.kv.remove(key);
V b = this.lv.remove(partner);
if (a != b)
throw new IllegalStateException("Contract violated");
return a;
}
private V removeL(L key)
{
K partner = this.lk.get(key);
if (partner == null)
throw new IllegalStateException("Contract violated");
V a = this.lv.remove(key);
V b = this.kv.remove(partner);
if (a != b)
throw new IllegalStateException("Contract violated");
return a;
}
public boolean containsKey(Object key)
{
Validate.notNull(key, "null keys not supported");
if(key.getClass().isAssignableFrom(this.k))
return this.containsKeyK((K) key);
else if(key.getClass().isAssignableFrom(this.l))
return this.containsKeyL((L) key);
throw new ClassCastException(String.format("Cannot cast %s to %s nor %s", key.getClass().toString(), this.k.toString(), this.l.toString()));
}
public boolean containsKeyK(K key)
{
L part = this.kl.get(key);
if (part == null)
throw new IllegalStateException("Contract violated");
boolean ret = this.kv.containsKey(key);
if (this.lv.containsKey(part) != ret)
throw new IllegalStateException("Contract violated");
return ret;
}
public boolean containsKeyL(L key)
{
K part = this.lk.get(key);
if (part == null)
throw new IllegalStateException("Contract violated");
boolean ret = this.lv.containsKey(key);
if (this.kv.containsKey(part) != ret)
throw new IllegalStateException("Contract violated");
return ret;
}
public static <K, L, V> AmirMap<K, L, V> create(Class<K> k, Class<L> l, Class<V> v)
{
if (k == l)
throw new IllegalArgumentException("K cannot be the same as L");
return new AmirMap<K, L, V>(k, l);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment