2012-02-12 68 views
21

我通過執行以下功能將傳入的字符串轉換爲哈希碼,但其中一些值爲負值。我不認爲散列值應該是負值。請告訴我我做錯了什麼。給予負值的HashCode

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

哈希碼爲什麼不能爲負數? AFAIK,對他們的唯一要求是相等的對象。 – user1096188 2012-02-12 15:33:46

+5

空間很好。 – AHungerArtist 2012-02-12 15:38:44

回答

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; 

目前還不清楚是什麼類型的這些表達都是,但我猜你結束了採取串的哈希碼......一個字符串,你並不真的需要創建第一個地方。雖然有更好的方法來獲取已知域的哈希碼,但上述方法很適合作爲通用哈希生成技術。

請注意,如果您避免使用縮寫,並且使用駱駝套管,例如,它也有助於代碼的可讀性。 sourceAddress而不是srcadd

+1

其實它是在一些論壇上寫的,「hashCode是一種計算一個長字符串的小型(32位)摘要數字鍵的方法」。所以,雖然它的範圍是2^32,從0到2^32 – Xara 2012-02-12 15:37:59

+3

@Zara:但是'int'不支持大於2^31 - 1的數字......它*是一個32位值,但是在一個有符號的範圍內。 – 2012-02-12 15:41:14

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 2015-11-21 05:00:38

+0

通過「大於2^31」,這個答案真的意味着「超過31個二進制數字」,而不是一個大於*整數*比2^31。爲什麼'(key.hashCode()&0x7fffffff)'?因爲對'hashCode()'的結果應該(或可能)比'Math.abs()'更快地執行,所以這是一個簡單的1步二進制操作。 – 2017-07-20 15:23:47

-1

您可以使用Math.abs(hash)從負數hashcode創建正值。