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); }
}