これは一種の学術的なポイントですが、Effective Javaや多くのSOの質問などの本でハッシュコードが推奨されている理由がわからないと、ハッシュコードを完全に理解できないと感じます。
仮定する:
public sealed class Point
{
private readonly int x;
private readonly int y;
//constructor ommited
//equals ommited
public override int GetHashcode()
{
int hash = 17; //why should the initial value be non-zero?
unchecked
{
hash = hash * 31 + x; //do not tell me why I should use primes - that is not the question
hash = hash * 31 + y;
return hash;
}
}
}
さて、おそらく、初期値の理由は、コンポーネントの1つがゼロである場合の衝突を減らすためです。
これが役立つ例を見つけるのに苦労しています。
これは衝突の一例ですが、初期値を持っていてもオッズはありません。
x y Hash Without initial value Hash With initial value
0 31 31 16368
1 0 31 16368
理想的には、初期値が衝突を防ぐ具体的な例を探しています。
初期値が決して違いを生まない理由についての私の理論
//Given a prime p, initial value i, fields a,b,c, calculate hash h
h = i;
h = h*p + a;
h = h*p + b;
h = h*p + c;
したがって:
h = ((i*p + a)*p + b)*p + c
= (ipp + ap + b )*p + c
= ippp + app + bp + c
したがって、初期値i
は、定数値(この場合はi*p
3 )を生成することにより、すべてのハッシュコードに同じように影響します。