私は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から開始する理由
これにより、ハッシュコードが互いに衝突しにくくなるという保証はありますか?
はい。たとえば、文字列の場合、文字列値に依存するため、ハッシュコードの衝突の可能性は非常に低いです。 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;
}