9

hashCodeメソッドの最適な実装で受け入れられた答えは、ハッシュコードを見つけるための一見良い方法を提供します。しかし、私はハッシュコードを初めて使用するので、何をすべきかよくわかりません。

1) の場合、選択したゼロ以外の値は重要ですか? 1素数などの他の数と同じくらい良い31ですか?

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


私はこのクラスでそれを正しく解釈しましたか:

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));
    }
}
4

2 に答える 2

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

実装が適切でないと見なされるアルゴリズムがいくつかありhashCodeます。属性値の単純な追加はその 1 つです。Integer その理由は、 aInteger bの2 つのフィールドを持つクラスがあり、hashCode()これらの値を合計するだけの場合、値の分布はhashCodeインスタンスが格納する値に大きく依存するためです。たとえば、a の値のほとんどが0から 10 の間にあり、bが 0 から 10 の間にある場合、hashCode値は 0 から 20 の間にあることになります。これは、たとえば、このクラスHashMapのインスタンスを格納すると、多数のインスタンスが同じバケットに格納されることを意味します (多数のインスタンスが異なるabを持つため)。値が同じであるが同じバケット内に配置されます)。ルックアップを実行すると、バケットのすべての要素が を使用して比較されるため、これはマップ上の操作のパフォーマンスに悪影響を及ぼしますequals()

アルゴリズムに関しては、問題ないように見えます。Eclipse が生成するものと非常に似ていますが、37 ではなく 31 という異なる素数を使用しています。

@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;
}
于 2013-05-18T23:14:02.923 に答える
6

long 値に対して適切に動作するハッシュコード メソッドが既に存在します。車輪を再発明しないでください。

int hashCode = Long.hashCode((a * 31 + b) * 31 + c); // Java 8+

int hashCode = Long.valueOf((a * 31 + b) * 31 + c).hashCode() // Java <8

素数 (JDK クラスでは通常 31) を乗算して合計を累積することは、複数の数値から「一意の」数値を作成する一般的な方法です。

Long の hashCode() メソッドは、範囲全体に適切に分散された結果を保持しint、ハッシュを「正常に動作する」ものにします (基本的に疑似乱数)。

于 2013-05-18T23:30:18.307 に答える