Eclipse 3.5 には、Java hashCode() 関数を生成する非常に優れた機能があります。たとえば、生成されます(少し短縮されます:)
class HashTest {
int i;
int j;
public int hashCode() {
final int prime = 31;
int result = prime + i;
result = prime * result + j;
return result;
}
}
(クラスにさらに属性がある場合は、result = prime * result + attribute.hashCode();
追加の属性ごとに繰り返されます。int の場合、.hashCode() は省略できます。)
これは問題ないように見えますが、プライムの選択は 31 です。これはおそらく、Java String の hashCode 実装から取られています。これは、ハードウェア乗算器の導入後、長い間使用されなくなったパフォーマンス上の理由から使用されていました。ここでは、i と j の小さな値に対して多くのハッシュコードの衝突があります。たとえば、(0,0) と (-1,31) は同じ値です。小さな値が頻繁に発生するので、これは Bad Thing(TM) だと思います。String.hashCode の場合、「Ca」や「DB」など、同じハッシュコードを持つ短い文字列も多数見つかります。大きな素数を取る場合、素数権を選択すればこの問題はなくなります。
私の質問: 選択するのに適した素数は何ですか? それを見つけるためにどのような基準を適用しますか?
これは一般的な質問であるため、i と j の範囲を示したくありません。しかし、ほとんどのアプリケーションでは、比較的小さな値が大きな値よりも頻繁に発生すると思います。(大きな値を持っている場合、素数の選択はおそらく重要ではありません。) 大きな違いはないかもしれませんが、より良い選択はこれを改善するための簡単で明白な方法です。Commons lang HashCodeBuilderも、奇妙なことに小さい値を提案します。
(明確化: これはWhy does Java's hashCode() in String use 31 as a Multiplier? の複製ではありません。なぜなら、私の質問は JDK の 31 の歴史には関係なく、新しいコードでより良い値になるものについてです同じ基本的なテンプレートを使用します.そこにある答えはどれもそれに答えようとしません.)