由于JDK实现的[Linked]HashMap
不允许您重写equals
/hashCode
实现,因此唯一的其他方法是:
a wrapping object like this:
class A {
private final String fieldA;
private final String fieldB;
}
class B {
private A a;
public int hashCode() {return a.fieldA.hashCode();}
public boolean equals(Object o) {... the same ... }
}
Map<B, Value> map = new HashMap<B, Value>();
map.put(new B(new A("fieldA", "fieldB")), new Value(0));
Well, with more getters/constructors.
This can be annoying, and perhaps there exists some library (like Guava) that allows an equals/hashCode method to be given like you can give a Comparator
to TreeMap
.
You'll find below a sample implementation that point out what to do to decorate an existing map.
use a TreeMap
with a specific Comparator
. The other answer point it, but I'd say you'll need to correctly define a Comparator
because this could lead to problems: if you compareTo
method returns 0 when equality is reached, and 1 in other case, this means there is no natural ordering. You should try to find one, or use the wrapper object.
如果您想接受挑战,您可以使用委托/装饰器在另一个HashMap(这可以是另一种地图,如LinkedHashMap)上创建基本实现:
如果您想接受挑战,您可以使用委托/装饰器在另一个HashMap(这可以是另一种地图,如LinkedHashMap)上创建基本实现:
public class DelegatingHashMap<K,V> implements Map<K,V> {
private final BiPredicate<K,Object> equalsHandler;
private final IntFunction<K> hashCodeHandler;
private final Map<Wrapper<K>,V> impl = new HashMap<>();
public DelegatingHashMap(
BiPredicate<K,Object> equalsHandler,
IntFunction<K> hashCodeHandler
) {
this.equalsHandler = requireNonNull(equalsHandler, "equalsHandler");
this.hashCodeHandler= requireNonNull(hashCodeHandler, "hashCodeHandler");
}
public Object get(K key) {
Wrapper<K> wrap = new Wrapper<>(key);
return impl.get(wrap);
}
...
static class Wrapper<K2> {
private final K2 key;
private final BiPredicate<K> equalsHandler;
private final IntFunction<K> hashCodeHandler;
public int hashCode() {return hashCodeHandler.apply(key);}
public boolean equals(Object o) {
return equalsHandler.test(key, o);
}
}
}
使用map的代码:
DelegatingHashMap<String, Integer> map = new DelegatingHashMap<>(
(key, old) -> key.equalsIgnoreCase(Objects.toString(o, "")),
key -> key.toLowerCase().hashCode()
);
map.put("Foobar", 1);
map.put("foobar", 2);
System.out.println(map);
但也许最好的记忆方法是重写 HashMap
,直接使用处理程序而不是包装器。