クラスのオーバーヘッドなしで速度が必要であると仮定すると、次のように*Set
記述できます。H
/**
* Hashes a set of integers.
*
* @param list to hash
* @return hash code
*/
public static int H(int list[]) {
// XOR all the integers together.
int hashcode = 0;
for (int val : list) {
hashcode ^= val;
}
return hashcode;
}
順番に関係なく同じで、比較的効率的です。
例えば:
public static void main(String[] args) {
System.out.println(Integer.toHexString(H(new int[]{0xabcd,0x1234,0x1111})));
System.out.println(Integer.toHexString(H(new int[]{0x1234,0x1111,0xabcd})));
}
表示:
a8e8
a8e8
これは、次のようにすることで、単なるint
s以外にも一般化できます。
/**
* Hashes a set of objects.
*
* @param list to hash
* @return hash code
*/
public static int H(Object list[]) {
// XOR all the hashes together.
int hashcode = 0;
for (Object val : list) {
hashcode ^= val.hashCode();
}
return hashcode;
}
その場合、プログラムはプリミティブmain
の代わりに の配列を使用する必要があります。 Integer
int
数値の追加はほぼ同じ速度で行われ、32 ビット範囲でより適切な分布が得られる可能性があります。セットの要素が範囲全体にすでに均一に分布している場合は、xor の方が適している可能性があります。
ただし、どちらの方法でも、整数を使用して衝突を簡単に作成できます。たとえば、adding メソッドを使用します。
{1000, 1001, 1002}
{0, 1, 3002}
これらの配列はどちらも同じH()
です。
XORメソッドを使用。
{0x1010, 0x0101}
{0x1111, 0x0000}
これらはどちらも同じH()
です。
同様に、0
リストはそれの有無にかかわらず同じハッシュを持つため、要素には問題があります。これは、反復ごとに定数値を追加することで軽減できます。例えば:
...
hashcode += val.hashCode() + CONSTANT;
...
または、要素の数を初期ハッシュ コードとして含めることにより、次のようにします。
...
// XOR all the hashes together.
int hashcode = list.length;
...