2013-04-12 7 views
5

私が正しく覚えていれば、Object型のオブジェクトのjavaでのデフォルトのhashCode()の実装は、オブジェクトのメモリアドレスを返すことです。独自のクラスを作成するときは、hashCode()をオーバーライドして、HashMap()などのハッシュ関連のコレクションに挿入するときに正しく動作するようにしたいと読んでいます。しかし、なぜメモリアドレスが悪いですか?Javaのデフォルトハッシュコード()がなぜ悪いのですか?

メモリが不足していて衝突が発生することがありますが、これが問題であることがわかっている唯一のケースは、データのTONSを処理しているメモリがほとんどなく、START Javaのハッシュ関連コレクションは連鎖によって衝突を解決するため(バケットは同じハッシュコード/インデックスに解決された値のリストにリンクします)、パフォーマンスに影響します。

+3

あなたは問題ではありません。 [this](http://stackoverflow.com/questions/27581/overriding-equals-and-hashcode-in-java?rq=1)を読むことができます。問題は、平等概念から独立して見ることはできません。 –

+1

何も悪いことはありませんが、他の理由で時々変更する必要があります。 – Affe

+0

デフォルトの 'hashCode()'はメモリアドレスとは関係ありません。このドキュメントでは、メモリアドレスをハッシュコード計算の入力として考えていますが、これは最近のJVMで実装された方法とは異なります。 – Holger

答えて

0

equalsメソッドを使用していない間は、hashCodeを定義しないでも問題ありませんが、hashCodeのコントラクトはオブジェクトに同じ結果を与えることになります。あなたはそれが確信することはできませんので、あなたは、すべてのオブジェクトが一意である場合は、デフォルトの実装では正常に動作しそれを自分

hashCode

20

を書き換える必要があります。しかし、equals()をオーバーライドすると、異なるアドレスを持つオブジェクトが互いに同等である可能性があることが暗黙のうちに示されます。その場合は、hashCode()もオーバーライドする必要があります。

Stringクラスについて考えてみましょう。

String s1 = new String("foo"); 
String s2 = new String("foo"); 

これらの2つの文字列は等しいので、それらのハッシュコードは同じでなければなりません。しかし、それらは異なる住所を持つ別個のオブジェクトです。

s1 == s2   // false, different addresses 
s1.equals(s2) // true, same contents 

これらのアドレスをハッシュコードとして使用するとエラーになります。したがって、StringはhashCode()をオーバーライドして、等しい文字列が等しいハッシュコードを持つようにします。その後、

a.equals(b)がtrueの場合、a.hashCode() == b.hashCode():これは会うのhashCode()の契約を、役立ちます。

ボトムライン:あなたは等号をオーバーライドする場合は()、ものhashCode()をオーバーライドします。

+0

ありがとう、それはすべてのように、あなたがどのように平等を定義するかによって異なります。あなたが指定した例では、文字列の値によって等価性が決定されたので、Object()のhashCode()はハッシュマップに2つの異なるエントリを持つため、どちらも同じですが悪いです。私はJavaが文字列のためにhashCode()をどのように実装したかを調べ、これを見つけました:http://java-bytes.blogspot.com/2009/10/hashcode-of-string-in-java.html;誰かがこれを説明したり、一般的にhashCode()をオーバーライドする方法を気にしますか?私がオンラインで見たすべての例は複雑に見えます。 –

+0

Josh BlochのEffective Javaは、これをうまくカバーし、実装の戦略を持っています。 Idesはまた、あなたにとって合理的な実装を生成します。たとえば、Employeeクラスはその従業員によって一意に識別される可能性があります。あなたがそれを使用する場合は、平等とハッシュを行います。 Josh Blochは、密接に関連した数字を広めるためにいくつかのテクニックを使用することを提案しています(ハッシュをより効率的にするためにコアJavaブックに説明されています)。等価とハッシュのメソッド – Romski

+0

私は、 "foo" Stringの例は、Javaのインターンの文字列リテラルと定数のため、s1 == s2は真であると確信しています。 – ChaimKut

1

ハッシュマップにオブジェクトを配置する際に使用される正確なキーオブジェクトは、後でプログラムでマップにアクセスするために使用できない場合があります。だから、あなたはequalsメソッドをオーバーライドさせるでしょう。 equalsメソッドをオーバーライドすると、ハッシュコードも同じであることが確認されます。そうでなければ、ハッシュマップからオブジェクトを取得できません。

0

データ構造がどのhashCode()実装を使用すべきかを決定することは、暗黙のうちにhashmap APIの一部です。

特定のAPIに厳重に処理されていない情報を提供すると、コントロールが手に持たなくなります。

()の実装にカップルあなたによって処理されていないメモリアドレスを管理したいキーをデフォルトのhashCodeを使用して、あなたは上の任意のコントロールを持っていません。

ある日、ある種のメモリオプティマイザを使用して、一貫性とパフォーマンスを向上させるためにメモリ上のオブジェクトを移動したいとします。 データ構造はキーの元のハッシュアドレスを保持するため、これ以上使用することはできません。ビューのより実用的な観点で

プログラム全体のデータ構造から値を取得するために、あなたは(で以前に挿入されているすべてのキーへの参照を保持する必要があります別のデータ構造を使用して)。 オブジェクトの状態に関して「似ている」キーを使用することはできません。

Person steve1 = new Person("Steve","21","engineer"); 
Person steve2 = new Person("Steve","21","engineer"); 

map.put(steve1,"great worker"); 

map.get(steve2); 
// returns null because "steve2" is not considered a key like "steve1" 

map.get(steve1); 
// returns "great worker" 
+1

あなたの答えは間違っています。ハッシュがキャッシュされ、オブジェクトはオブジェクトの存続期間中、デフォルトのハッシュを維持します。 e、hashCodeは自明にアドレスを返すことはできません。 – Andy

関連する問題