1. ホーム
  2. java

[解決済み] Java の String の hashCode() では、なぜ 31 が乗数として使われるのですか?

2022-03-19 03:45:22

質問

Java のドキュメントによると ハッシュコード に対して String オブジェクトは次のように計算されます。

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

を使って int の算術演算を行い、ここで s[i] i の文字が含まれる。 n は長さ 文字列、および ^ は指数を示す。

なぜ31が乗数として使われるのですか?

乗数は比較的大きな素数であるべきだと理解しています。では、なぜ29や37、あるいは97でないのか?

解き方は?

ジョシュア・ブロッホの 効果的なJava (この本はあまりお勧めできない本で、stackoverflowで何度も言及されているおかげで購入しました)。

<ブロッククオート

31という値が選ばれたのは、奇数素数だからです。もし偶数で、掛け算がオーバーフローした場合、2の掛け算はシフトと同じなので、情報が失われてしまうからです。素数を使うメリットはあまり明確ではないが、伝統的なものである。31の良い特性は、掛け算をシフトと引き算に置き換えて、パフォーマンスを上げることができることです。 31 * i == (i << 5) - i . 最近のVMはこのような最適化を自動で行ってくれます。

(第3章 項目9: equals を上書きするときは必ずハッシュコードを上書きする、48ページより)