我相信如果我声明一个HashMap并重复提供它的Map.Entry实例,最终哈希码将与另一个哈希码冲突,即使这两个键(碰巧是我的需要的字符串)是不同的。
此时,HashMap和其他使用散列的类将生成一个不同的哈希码,作为内部使用的真正密钥。 (编辑:事实证明这不是真的。请看选定的答案。)
有没有办法获得内部密钥?我想要它的原因是因为32位密钥比真实世界密钥更有效的内存和速度,这可能是一个(可能)长字符串。
我可以为我的字符串创建一个哈希码注册表,但是如果Java已经可以做到这一点,为什么还要这么做呢。
答案 0 :(得分:8)
否即可。 无法为系统中的每个可能对象获取唯一的32位数字。
对此最简单的证明是,在具有足够内存量的64位JVM上,您可以轻松地拥有超过2 ^ 32个对象:因此您需要超过2 ^ 32个不同的哈希值。但由于您只有32位来存储这些哈希值,因此您不能获得超过2 ^ 32个不同的哈希值。这称为Pidgeonhole principle。
另外:HashMap
不会生成“唯一哈希码”:它只是将具有相同哈希码的所有元素存储在同一个存储桶中(在链表中)并进行检查如果必须检索其中一个,则每个人都使用equals()
。
答案 1 :(得分:2)
强制性链接:Hash table - 只有少数情况甚至允许minimal perfect hashing,而
}实际上有两个因素,它们都与pigeon hole principle相关:HashMap
所代表的唯一对象:哈希值不能保证唯一。也就是说,散列函数的范围小于唯一对象的范围。(另外,a hash code has a strict relationship with object-equality,如果每个对象都有一个“唯一系统哈希码”,那么所述哈希码可以用在对象身份映射中,但不能用于对象相等映射。)
由于这些原因,在一般的哈希表实现中始终需要collision resolution 。 (OpenJDK 7 HashMap implementation使用链接列表链接方法,最终相等由int
和bucket_used = hash % bucket_count
按顺序决定。)
虽然JDK实现确实使用内部“哈希混合器”,目的是创建更好的哈希值分布,但这与哈希表如何处理冲突无关,就像原始哈希一样功能,受上述相同规则的约束。
快乐的编码。
答案 2 :(得分:1)
不,它不会产生不同的哈希码。它将使用相同的哈希代码维护多个条目,并且可以轻松查找具有相同哈希码的所有条目。当您尝试使用该哈希代码查找密钥时,它将检查与所有哈希匹配密钥的相等性,直到找到相等匹配或用完为止。阅读HashMap
的代码以了解更多详情。
当可以有超过2个 32 个不同的对象时,您期望HashMap
产生一个真正独特的int
哈希值?