2013-05-18 18 views
9

Best implementation for hashCode methodで受け入れられた答えは、ハッシュコードを見つけるための一見良い方法を提供します。しかし、私はハッシュコードの新機能なので、何をすべきか分かりません。良いhashCode()実装

1)については、私が選択した非ゼロ値は重要ですか? 1は素数31などの他の数字と同じくらい良いですか?

2)については、それぞれの値をcに追加しますか? longintdoubleなどの2つのフィールドがある場合はどうなりますか?


は私が右のこのクラスでそれを解釈しました:

public MyClass{ 
    long a, b, c; // these are the only fields 
    //some code and methods 
    public int hashCode(){ 
     return 37 * (37 * ((int) (a^(a >>> 32))) + (int) (b^(b >>> 32))) 
       + (int) (c^(c >>> 32)); 
    } 
} 

答えて

15
  1. 値が重要ではありません、それはあなたが望むものは何でもすることができます。素数はhashCode値のより良い分布をもたらし、従って好ましい。
  2. あなたは必要はない、それらを追加する必要があり、あなたがいる限り、それはhashCodecontractを満たして、あなたが好きなアルゴリズムを実装するのは自由です:それはより多くの同じオブジェクトで呼び出されるたび
  • オブジェクトの等価比較で使用される情報が変更されていない場合、hashCodeメソッドは一貫して同じ整数を返す必要があります。この整数は、アプリケーションの1回の実行から同じアプリケーションの別の実行まで一貫している必要はありません。
  • equals(Object)メソッドで2つのオブジェクトが等しい場合は、2つのオブジェクトのそれぞれでhashCodeメソッドを呼び出すと、同じ整数結果が生成される必要があります。
  • equals(java.lang.Object)メソッドで2つのオブジェクトが等しくない場合は、2つのオブジェクトのそれぞれでhashCodeメソッドを呼び出すと、別々の整数結果が生成される必要はありません。しかし、プログラマは、不等なオブジェクトに対して別個の整数結果を生成すると、ハッシュテーブルのパフォーマンスが向上する可能性があることに注意する必要があります。

は、属性値は、そのうちの一つであることの追加単純ではありません良いhashCode実装として考えることができるいくつかのアルゴリズムがあります。その理由は、次の2つのフィールドを持つクラスを持っている場合は、IntegerIntegerBとあなたのhashCode()だけで、これらの値は、その後hashCode値の分布が非常に値があなたのインスタンスストアに依存されてまとめています。例えば、,の値の大部分が0-10とbの間にある場合、値は0-20の間である。これは、たとえば、このクラスのインスタンスをHashMap多くのインスタンスは同じバケットに格納されます(bの値が同じですが、同じ合計のインスタンスが同じバケットに入れられるため)。これは、ルックアップを行うときに、バケットからのすべての要素がequals()を使用して比較されるため、マップ上の操作のパフォーマンスに悪影響を及ぼします。

アルゴリズムに関しては、それは正常に見える、それは、Eclipseが生成するものと非常に類似しているが、それは異なる素数、31ない37使用されている:既に

@Override 
public int hashCode() { 
    final int prime = 31; 
    int result = 1; 
    result = prime * result + (int) (a^(a >>> 32)); 
    result = prime * result + (int) (b^(b >>> 32)); 
    result = prime * result + (int) (c^(c >>> 32)); 
    return result; 
} 
+0

どのような種類のアルゴリズムが良いですか?例のものは良いですか?各要素に異なる素数を使うべきですか? – Justin

+0

私はあなたの#1を理解していますが、衝突が少なくなる方が良いです。 – Justin

+0

すべてのコードは何でもかまいませんが、*良い*コードであるために、hadhCodeは "何も"あってはいけません。 Object.hashCode()を参照してください。 – Bohemian

5

行儀ハッシュコード方式長い値のために存在する - 車輪を再発明していない:

int hashCode = Long.valueOf((a * 31 + b) * 31 + c).hashCode(); 

素数(JDKクラスでは通常31)を乗じ、その合計を累積することは、いくつかの数字から「ユニーク」番号を作成する一般的な方法です。

LongのhashCode()メソッドは、intの範囲に正しく分布された結果を保持し、ハッシュを「正常に動作します」(基本的に疑似ランダム)にします。

+0

これは 'int hashCode = 31 *(31 *(a)(a >>> 32))+ 31)+(int)(b^>> 32)))+(int)(c ^(c >>> 32)) '?言い換えれば、値のハッシュコードを組み合わせる方が良いでしょうか?( '(int)(a ^(a >>> 32))' == 'Long.valueOf(a).hashCode()')値の組み合わせのハッシュコード? – Justin

+4

@gangqinlaohu知らないが、私は知る必要はありません。私は、ハッシングのためのJDKコードがあなたが思い付く何よりも良くなることを保証することができます。これらのクラスは厳密にテストされ、研究されています。また、私のコードをあなたのものよりも読むのが簡単です。それだけで貴重です。 B)私は最後にハッシュするほうがいいと思うし(コードも少なくて済む)、個々のハッシュの組み合わせ(おそらくちょうど追加する)を受け入れるだろう。 – Bohemian

+0

「a = 3」、「b = 2」を追加するだけで、「c = 13」は「a = 2」、「b = 3」、「c = 13」(および他のものと同じhashCodeを返します同様の値) – Justin

関連する問題