刚开始在我的一个课程中学习哈希表。我的理解是它们的工作方式是表中元素的索引应该用哈希函数来确定。我正在尝试为一个大的字符串列表创建一个哈希表,我们的讲师鼓励我们使用Java的String方法hashCode()
。假设我想将所有这些字符串放在一个数组中words[]
。
这是我没有得到的。我该怎么办这个号码?产生的哈希值似乎很大。 “stack”的哈希码是109757064,而“overflow”的哈希码是529642498.这是一个超过4亿的差异,并且将是一个非常荒谬的巨大表,更不用说有多少索引没有分配给它们的String 。所以我可以words[109757064] = "stack"
和words[529642498] = "overflow"
,但这显然是荒谬的。
我在这里缺少什么?在获取哈希码并在我的数组中为其分配索引之间是否有一个步骤?
答案 0 :(得分:1)
是的,有。
你从那个巨大的哈希码开始,然后再次哈希,以匹配你拥有的桶数。
可以是一个简单的code % buckets
。
java.util.HashMap
使用的real-life implementation基本上是(code & (buckets - 1)
),但他们首先应用另一个哈希函数来防止一些麻烦的边缘情况。
257 /**
258 * Applies a supplemental hash function to a given hashCode, which
259 * defends against poor quality hash functions. This is critical
260 * because HashMap uses power-of-two length hash tables, that
261 * otherwise encounter collisions for hashCodes that do not differ
262 * in lower bits. Note: Null keys always map to hash 0, thus index 0.
263 */
264 static int hash(int h) {
265 // This function ensures that hashCodes that differ only by
266 // constant multiples at each bit position have a bounded
267 // number of collisions (approximately 8 at default load factor).
268 h ^= (h >>> 20) ^ (h >>> 12);
269 return h ^ (h >>> 7) ^ (h >>> 4);
270 }
271
272 /**
273 * Returns index for hash code h.
274 */
275 static int indexFor(int h, int length) {
276 return h & (length-1);
277 }