sclass DoubleKeyedMap { new Map> map1; new Map> map2; Cl getA(A a) { ret map1.get(a); } Cl getB(B b) { ret map2.get(b); } Cl valuesForA(A a) { ret values(getA(a)); } Cl valuesForB(B b) { ret values(getB(b)); } C get(A a, B b) { ret mapGet(map1.get(a), b); } C get(Pair p) { ret p == null ? null : get(p.a, p.b); } void put(A a, B b, C c) { mapGetOrCreateHashMap(map1, a).put(b, c); mapGetOrCreateHashMap(map2, b).put(a, c); } void put(Pair p, C c) { put(p.a, p.b, c); } Set aKeys() { ret keys(map1); } Set bKeys() { ret keys(map2); } }