2012-02-12 8 views
21

次の関数を実行することで、入ってくる文字列をハッシュコードに変換していますが、値の一部が負です。私はハッシュ値が負でなければならないとは思わない。私が間違っていることを教えてください。負の値を与えるHashCode

int combine = (srcadd + dstadd + sourceport + destinationport + protocol).hashCode(); 
System.out.println(combine); 
+5

ハッシュコードが負でないのはなぜですか? AFAIK、それらの唯一の要件は等しいオブジェクトのために等しくなることです.. – user1096188

+5

スペースはいいです。 – AHungerArtist

答えて

35

私は、ハッシュ値が負でなければならないと思います。

負のハッシュコードを持つことはまったく有効です。ハッシュコードを思いつく多くの方法は、自然に負の値になり、それらを扱うものはすべてこれを考慮する必要があります。しかし、私は、あなたのハッシュコードを思い付く別のアプローチを考えています。

int hash = 17; 
hash = hash * 31 + srcadd.hashCode(); 
hash = hash * 31 + dstadd.hashCode(); 
hash = hash * 31 + sourceport; // I'm assuming this is an int... 
hash = hash * 31 + destinationport; // ditto 
hash = hash * 31 + protocol.hashCode(); 
return hash; 

それは、これらの式の型が何であるかは明らかではないのですが、私は...あなたは、文字列のハッシュコードを取って終わるているあなたが本当にで作成する必要はありません文字列を推測しています最初の場所。既知のドメインに対してハッシュコードを取得するためのより良いアプローチがありますが、上記のアプローチは、汎用のハッシュ生成技術としてうまく機能します。

略語を避けるとコードの可読性が向上し、ラクダケーシング(例: srcaddの代わりにsourceAddressです。

+1

実際には、「hashCodeは、長い文字列から小さな(32ビット)ダイジェスト数値キーを計算する方法です」と書かれています。その範囲は2^32で0から2^32 – Xara

+3

@Zara:しかし、 'int'は2^31-1より大きい数値をサポートしていません。それは* 32ビット値ですが、符号付きの範囲です。 –

17

時にはhashcodeの計算自体がInteger.MAX_VALUEを超えます。つまり、2147483647です。そのとき起こるのは、overflowの後に負の整数を得ることです。 ネガティブハッシュコードは完全に有効です!

10

ハッシュコードを持っていることは完全に合法である、とあなたはハッシュ値あなたはMath.abs(hash)を使用することができ、ハッシュベースのコレクションに使用されるようなを探している場合。これはまた、ハッシュが2^31より大きいときに負の数を与えることができ、最善の方法はシフトマスク(key.hashCode() & 0x7fffffff) % Mを使用することです(Mはテーブルサイズです)。

+1

Math.abs(ハッシュ)を使用しない理由がわかりません。 Math.abs()はint.MIN_VALUEに対してのみ負の値を返します。 hash = key.hashCode()%Mの場合、hash == int.MIN_VALUEで終わる唯一の方法は、M> int.MAX_VALUEの場合です。この場合は、とにかに表を索引付けするためにlongを使用する必要があります。 – jkindwall

+0

"2^31より大きい"とは、実際には2^31より大きい*整数ではなく、31以上の2進数を意味します。なぜ '(key.hashCode()&0x7fffffff)'なのですか? 'hashCode()'の結果に対するシンプルな1ステップバイナリ演算であるため、 'Math.abs()'より速く実行する必要があります。 –

-1

Math.abs(hash)を使用すると、負の値hashcodeから正の値を作成できます。

関連する問題