// A: object type
// B: hash type (e.g. Long)
sclass UniquifyUsingHasher {
settable IF1 hasher;
settable IF2 equalsPredicate = l2 eq;
*(IF1 *hasher) {}
*(IF1 *hasher, IF2 *equalsPredicate) {}
new MultiMap byHash;
gettable new L list;
bool add(A a) {
B hash = hasher.get(a);
if (any(byHash.get(hash), x -> equalsPredicate.get(x, a)))
false;
byHash.put(hash, a);
list.add(a);
true;
}
selfType addAll(Iterable extends A> l) {
fOr (A a : l)
add(a);
this;
}
L get() { ret list; }
int nHashCollisions() { ret l(keysWithMultipleValues(byHash)); }
}