static final class SmallestListMultiMap {
Map data = new HashMap(); // values are smallestLists
*() {}
*(bool useTreeMap) { if (useTreeMap) data = new TreeMap; }
*(MultiMap map) { putAll(map); }
void put(A key, B value) { synchronized(data) {
O list = data.get(key);
data.put(key, smallestList_add(list, value));
}}
void addAll(A key, Collection values) { synchronized(data) {
putAll(key, values);
}}
void addAllIfNotThere(A key, Collection values) { synchronized(data) {
for (B value : values)
setPut(key, value);
}}
void setPut(A key, B value) { synchronized(data) {
if (!containsPair(key, value))
put(key, value);
}}
boolean containsPair(A key, B value) { synchronized(data) {
ret smallestList_contains(get(key), value);
}}
void putAll(A key, Collection values) { synchronized(data) {
for (B value : values)
put(key, value);
}}
void removeAll(A key, Collection values) { synchronized(data) {
for (B value : values)
remove(key, value);
}}
List get(A key) { synchronized(data) {
ret smallestList_toList(data.get(key));
}}
Set keySet() { synchronized(data) {
return data.keySet();
}}
Set keys() { synchronized(data) {
return data.keySet();
}}
void remove(A key) { synchronized(data) {
data.remove(key);
}}
void remove(A key, B value) { synchronized(data) {
O list = data.get(key);
if (list != null) {
O list2 = smallestList_remove(list, value);
if (list2 != list)
if (list2 == null)
data.remove(key);
else
data.put(key, list2);
}
}}
void clear() { synchronized(data) {
data.clear();
}}
boolean containsKey(A key) { synchronized(data) {
return data.containsKey(key);
}}
B getFirst(A key) { synchronized(data) {
ret (B) smallestList_get(data.get(key), 0);
}}
void putAll(MultiMap map) { synchronized(data) {
for (A key : map.keySet())
putAll(key, map.get(key));
}}
int keysSize() { synchronized(data) { ret l(data); }}
// full size - note: expensive operation
int size() { synchronized(data) {
int n = 0;
for (O l : data.values())
n += smallestList_l(l);
ret n;
}}
// expensive operation
L reverseGet(B b) { synchronized(data) {
new L l;
for (A key : data.keySet())
if (smallestList_contains(data.get(key), b))
l.add(key);
ret l;
}}
Map> asMap() { synchronized(data) {
new HashMap> map;
for (A key : data.keySet())
map.put(key, smallestList_toList(data.get(key)));
ret map;
}}
bool isEmpty() { synchronized(data) { ret data.isEmpty(); }}
}