簡単な質問:HashMap
カスタムクラスをキーとして使用する場合、関数をオーバーライドする必要がありますか?hashCode
その関数をオーバーライドしない場合、どのように機能しますか?
6 に答える
hashCode AND equalsをオーバーライドしない場合、内容に関係なく、各オブジェクトが異なるというデフォルトの動作が得られます。
hashCode()
関数をオーバーライドする必要がないのは、オーバーライドしない場合だけなので、参照の等式equals
のデフォルトの定義を使用します。Object.equals
これは、希望するものである場合とそうでない場合があります。特に、フィールド値が同じであっても、異なるオブジェクトは等しいとは見なされません。
オーバーライドしても動作が定義されequals
ていない場合(読み取り:まったく意味がなく、完全に破損します)hashCode
。HashMap
技術的には、等しいオブジェクトが同じhashCodeを持っている限り、hashCodeメソッドをオーバーライドする必要はありません。
したがって、Objectで定義されたデフォルトの動作を使用する場合、equalsは同じインスタンスに対してのみtrueを返しますが、hashCodeメソッドをオーバーライドする必要はありません。
ただし、equalsメソッドとhashCodeメソッドをオーバーライドしない場合は、常に同じキーインスタンスを使用していることを確認する必要があります。
例えば:
MyKey key1_1 = new MyKey("key1");
myMap.put(key1_1,someValue); // OK
someValue = myMap.get(key1_1); // returns the correct value, since the same key instance has been used;
MyKey key1_2 = new MaKey("key1"); // different key instance
someValue = myMap.get(key1_2); // returns null, because key1_2 has a different hashCode than key1_1 and key1_1.equals(key1_2) == false
実際には、キーのインスタンスが1つしかないことが多いため、技術的には、equalsメソッドとhashCodeメソッドをオーバーライドする必要はありません。
ただし、キーとして使用されるクラスのequalsメソッドとhashCodeメソッドをオーバーライドすることをお勧めします。これは、後であなたや別の開発者が同じインスタンスを使用する必要があることを忘れてしまい、問題の追跡が困難になる可能性があるためです。
注:equalsメソッドとhashCodeメソッドをオーバーライドする場合でも、equalsメソッドまたはhashCodeメソッドの結果を変更するような方法でキーオブジェクトを変更しないようにする必要があります。そうしないと、マップで値が見つかりません。もう。そのため、可能であれば不変オブジェクトをキーとして使用することをお勧めします。
キーとして使用しているオブジェクトクラスによって異なります。あなたが提案するようなカスタムクラスであり、何も拡張しない(つまり拡張するObject
)場合、hashCode関数はの関数になり、Object
メモリ参照を考慮して、同じように見える2つのオブジェクトを異なるコードにハッシュします。
そうhashCode()
です、あなたがあなたのために働くことがわかっている関数でクラスを拡張しているのでない限り、あなたはあなた自身のものを実装する必要があります。また、必ず実装してequals()
ください。のような一部のクラスArrayList
はequalsのみを使用しますが、HashMapのような他のクラスはとの両方をチェックしhashCode()
ますequals()
。
キーが不変でない場合は、問題が発生する可能性があることも考慮してください。変更可能なキーを含むエントリをマップに配置し、後でハッシュコードに影響を与えるようにキーを変更すると、マップ内のエントリが失われる可能性があります。これは、それを取得できなくなるためです。
Objectクラスのメソッドequals()
とメソッドをオーバーライドする必要があります。から継承されるおよびhashCode()
のデフォルトの実装は、オブジェクトインスタンスのメモリ位置を使用します(例)。これは、オブジェクトの2つのインスタンスが同じプロパティを持っているが、2つのインスタンスで異なるを使用するため、継承されたものが返される場合に問題を引き起こす可能性があります。equals()
hashcode()
java.lang.Object
MyObject@6c60f2ea
equals()
false
memory location
また、toString()
メソッドをオーバーライドして、オブジェクトの適切な文字列表現を提供することもできます。
ユーザー定義キーを実装する際の主な考慮事項
- クラスがをオーバーライドする場合は、をオーバーライド
equals()
する必要がありますhashCode()
。 - 2つのオブジェクトが等しい場合、それらの
hashCode
値も等しくなければなりません。 - フィールドがで使用されていない場合は、で使用し
equals()
てはなりませんhashCode()
。 - 頻繁にアクセスされる場合
hashCode()
は、パフォーマンスを向上させるためのキャッシュの候補です。