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();
则为每个附加属性重复。对于 ints .hashCode() 可以省略。)
这似乎很好,但对于素数的选择 31。它可能取自Java String 的 hashCode 实现,它是出于性能原因而使用的,在引入硬件乘法器之后早已不复存在。在这里,对于 i 和 j 的小值,您有许多哈希码冲突:例如 (0,0) 和 (-1,31) 具有相同的值。我认为这是一件坏事(TM),因为小值经常出现。对于 String.hashCode,您还会发现许多具有相同哈希码的短字符串,例如“Ca”和“DB”。如果你取一个大素数,如果你选择素数,这个问题就会消失。
所以我的问题是:什么是好的素数?你用什么标准来找到它?
这是一个一般性问题——所以我不想给出 i 和 j 的范围。但我想在大多数应用程序中,相对较小的值比较大的值更频繁地出现。(如果你有很大的值,那么选择素数可能并不重要。)它可能没有太大的区别,但更好的选择是改进这一点的简单而明显的方法 - 那么为什么不这样做呢?Commons lang HashCodeBuilder还提出了奇怪的小值。
(澄清:这不是Why does Java's hashCode() in String use 31 as a multiplier?的重复?因为我的问题不关心JDK中31的历史,而是关于新代码中什么是更好的价值使用相同的基本模板。那里没有一个答案试图回答这个问题。)