の JDK 実装では/実装[Linked]HashMap
をオーバーライドできないため、他の方法は次のとおりです。equals
hashCode
次のようなラッピング オブジェクト:
class A {
private final String fieldA; // equals/hashCode based on that field.
private final String fieldB; // equals/hashCode based on that field.
}
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));
さて、より多くのゲッター/コンストラクターを使用します。
Comparator
これは面倒な場合があり、 toを指定できるように equals/hashCode メソッドを指定できるライブラリ (Guava など) が存在する可能性がありますTreeMap
。
以下に、既存のマップを装飾するために何をすべきかを指摘する実装例を示します。
TreeMap
aを特定の とともに使用しComparator
ます。Comparator
他の答えはそれを指摘していますが、これは問題につながる可能性があるため、 a を正しく定義する必要があると思いますcompareTo
.同等に達したときにメソッドが 0 を返し、それ以外の場合は 1 を返す場合、これは自然な順序付けがないことを意味します. 探してみるか、ラッパー オブジェクトを使用してください。
挑戦したい場合は、委譲/別の装飾を使用して基本的な実装を作成できます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);
}
}
}
そして、マップを使用したコード:
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); // print {foobar: 2}
しかし、おそらく (メモリにとって) 最善のHashMap
方法は、ラッパーの代わりにハンドラーを直接使用するように を書き直すことです。