[解決済み] JavaでequalsとhashCodeのメソッドをオーバーライドする必要があるのはなぜですか?
質問
最近、こんな記事を読みました。 デベロッパーワークスドキュメント .
を定義するためのドキュメントです。
hashCode()
と
equals()
を効果的かつ正確に実行することができます。しかし、なぜこの2つのメソッドをオーバーライドする必要があるのかが理解できません。
これらのメソッドを効率的に実装するには、どのような判断をすればよいでしょうか。
どのように解決するのか?
Effective JavaについてJoshua Blochが語る
<ブロッククオートequals() をオーバーライドするすべてのクラスで hashCode() をオーバーライドする必要があります。そうしないと、Object.hashCode() の一般契約に違反することになり、HashMap、HashSet、Hashtable など、すべてのハッシュベースのコレクションと連携してクラスが正しく機能しなくなる。
をオーバーライドするとどうなるのか、例を挙げて理解してみましょう。
equals()
をオーバーライドせずに
hashCode()
を使用しようとすると
Map
.
このようなクラスがあり、2つのオブジェクトが
MyClass
が等しい場合、その
importantField
が等しい(と
hashCode()
と
equals()
eclipseで生成されたもの)
public class MyClass {
private final String importantField;
private final String anotherField;
public MyClass(final String equalField, final String anotherField) {
this.importantField = equalField;
this.anotherField = anotherField;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((importantField == null) ? 0 : importantField.hashCode());
return result;
}
@Override
public boolean equals(final Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
final MyClass other = (MyClass) obj;
if (importantField == null) {
if (other.importantField != null)
return false;
} else if (!importantField.equals(other.importantField))
return false;
return true;
}
}
次のようなものがあるとします。
MyClass first = new MyClass("a","first");
MyClass second = new MyClass("a","second");
オーバーライドのみ
equals
もし
equals
がオーバーライドされている場合
myMap.put(first,someValue)
を呼び出すと、まず何らかのバケツにハッシュされます。
myMap.put(second,someOtherValue)
は他のバケツにハッシュされます(それぞれ異なる
hashCode
). つまり、同じバケツにハッシュされないので、両者は等しいのですが、マップはそれを認識できず、両者はマップの中に残ります。
をオーバーライドする必要はありませんが
equals()
をオーバーライドすると
hashCode()
の2つのオブジェクトがあることを知っている場合、何が起こるか見てみましょう。
MyClass
が等しい場合、その
importantField
は等しいが、オーバーライドはしない。
equals()
.
オーバーライドのみ
hashCode
をオーバーライドするだけなら
hashCode
を呼び出すと
myMap.put(first,someValue)
は、まず最初に、その
hashCode
を作成し、所定のバケットに格納する。そして
myMap.put(second,someOtherValue)
と同じように、1番目を2番目に置き換える必要があります。
マップドキュメント
というのは、(ビジネス要件によれば)両者は等しいからです。
しかし問題は、equalsが再定義されていないため、マップがハッシュ化したときに
second
というオブジェクトがあるかどうか、バケツを反復して調べます。
k
そのような
second.equals(k)
が真であれば
second.equals(first)
は
false
.
分かりやすかったでしょうか?
関連
-
[解決済み] Java enumのメンバーを比較する:==またはequals()?
-
[解決済み] JavaにおけるHashMapとHashtableの違いは何ですか?
-
[解決済み] Javaにおけるpublic、protected、package-private、privateの違いは何ですか?
-
[解決済み] serialVersionUIDとは何ですか、またなぜそれを使用する必要がありますか?
-
[解決済み] リフレクションとは何か、なぜ有用なのか?
-
[解決済み] Javaで配列を宣言し、初期化する方法は?
-
[解決済み] Java の配列を表示する最も簡単な方法は何ですか?
-
[解決済み] なぜJavaにはtransientフィールドがあるのですか?
-
[解決済み] EqualsメソッドがオーバーライドされたときにGetHashCodeをオーバーライドすることが重要な理由は何ですか?
-
[解決済み] JavaでequalsとhashCodeをオーバーライドする際に考慮すべき事項は?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
この行に複数のマーカーがある - HttpServletResponseが型エラーに解決できない
-
javaの実行中に「javaの例外が発生しました」と表示された場合はどうすればよいですか?
-
スキャナは、タイプに解決することはできません最もルーキー初心者の質問
-
Java コンパイルエラー - スレッド "main" で例外 java.lang.Error: 未解決のコンパイル問題です。
-
リソースの読み込みに失敗しました。サーバーはステータス500(内部サーバーエラー)で応答しました。
-
マスキング このリソースにアクセスするには、完全な認証が必要です。
-
javaコンパイル時のエラー:不正な文字 '\ufeff' に対する解決策です。
-
javaでよく使われる英単語
-
HttpClientがGZIP形式でない場合の対処法
-
maven プラグイン エラー プラグインの実行は、ライフサイクル構成ソリューションの対象外です。