web-dev-qa-db-ja.com

JavaのStringのhashCode()メソッドの背後には何がありますか?

私はJava=のhashCode()メソッドを調査しており、Stringクラスの奇妙なものを見つけました。ソースコードは次のとおりです。

public int hashCode() {
    int h = hash;
    if (h == 0 && value.length > 0) {
        char val[] = value;

        for (int i = 0; i < value.length; i++) {
            h = 31 * h + val[i];
        }
        hash = h;
    }
    return h;
}

コード自体は非常に単純です。しかし、このようにハッシュコードを計算する理由は何でしょうか?
31を選択する理由
value.length-1ではなく0から開始する理由
これにより、ハッシュコードが互いに衝突しにくくなるという保証はありますか?

29
HarryLv

はい。たとえば、文字列の場合、文字列値に依存するため、ハッシュコードの衝突の可能性は非常に低いです。 new演算子でStringを作成していない場合、新しいStringの値が既に存在する場合、新しいStringオブジェクトは作成されず、ヒープの古い値を参照します。この場合、hashCodeの値のみが参照されます予想と同じです。

HashCodeの一般的な契約は次のとおりです。

Javaアプリケーションの実行中に同じオブジェクトで複数回呼び出されるたびに、hashCodeメソッドは、オブジェクトの等価比較で使用される情報が変更されない限り、一貫して同じ整数を返す必要があります。この整数は、あるアプリケーションの実行から同じアプリケーションの別の実行まで一貫性を保つ必要はありません。

From Java 1.2、Java.lang.Stringクラスは、文字列のテキスト全体に対して積和アルゴリズムを使用してhashCode()を実装します。[2] Java.langのインスタンスsを指定します。たとえば、文字列クラスのハッシュコードは、h(s)

h(s)=s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]

ここでJava 32ビット整数の加算を使用して用語が合計されます。s[i]は文字列のi番目の文字を示し、nはsの長さです。

Apache Harmonyで参照するためのメソッドhashCodeは次のとおりです。

public int hashCode() {
    if (hashCode == 0) {
        int hash = 0, multiplier = 1;
        for (int i = offset + count - 1; i >= offset; i--) {
            hash += value[i] * multiplier;
            int shifted = multiplier << 5;
            multiplier = shifted - multiplier;
        }
        hashCode = hash;
    }
    return hashCode;
}
4
Shreyos Adikari