As @azurefrog points out, the behaviour you want isn't provided by TreeMap directly, so you will need a wrapper class of some sort. Here's an example; I've used TreeMaps for the internal implementation, but unless you want to use the ordering somehow with more methods, it's better to use a HashMap instead since then you get O(1) get and put operations, instead of O(log n).
import java.util.Map;
import java.util.TreeMap;
public class TwoKeysMap<K1 extends Comparable<K1>, K2 extends Comparable<K2>, V> {
private static class Entry<K1 extends Comparable<K1>, K2 extends Comparable<K2>, V> {
private final K1 k1;
private final K2 k2;
private final V v;
private Entry(K1 k1, K2 k2, V v) {
this.k1 = k1;
this.k2 = k2;
this.v = v;
}
}
private final Map<K1, Entry<K1, K2, V>> map1 = new TreeMap<>();
private final Map<K2, Entry<K1, K2, V>> map2 = new TreeMap<>();
public V getByKey1(K1 k1) {
Entry<K1, K2, V> e = map1.get(k1);
return e != null ? e.v : null;
}
public V getByKey2(K2 k2) {
Entry<K1, K2, V> e = map2.get(k2);
return e != null ? e.v : null;
}
public void put(K1 k1, K2 k2, V v) {
Entry<K1, K2, V> e = new Entry<>(k1, k2, v);
map1.put(k1, e);
map2.put(k2, e);
}
}
Usage:
> TwoKeysMap<String, Integer, Object> map = new TwoKeysMap<>();
> map.put("alice", 124221, "Object 1");
> map.put("bob", 241241, "Object 2");
> map.getByKey1("alice")
"Object 1" (Object)
> map.getByKey2(124221)
"Object 1" (Object)
Note that the inner Entry
class isn't strictly needed for just "get" and "put", but if you want to remove by key1 then the entry needs to store key2 too so you can remove from both maps, and vice versa:
public void removeByKey1(K1 k1) {
Entry<K1, K2, V> e = map1.remove(k1);
if(e != null) {
map2.remove(e.k2);
}
}
public void removeByKey2(K2 k2) {
Entry<K1, K2, V> e = map2.remove(k2);
if(e != null) {
map1.remove(e.k1);
}
}