某些哈希表方案(例如cuckoo hashing或dynamic perfect hashing)依赖于universal hash functions的存在以及能够收集展示冲突的数据并通过选择一个来解决这些冲突的能力来自通用散列函数族的新散列函数。
前一段时间我试图在由cuckoo散列支持的Java中实现哈希表并遇到麻烦,因为虽然所有Java对象都有hashCode
函数,但hashCode
返回的值是固定的每个对象(当然,除非对象发生变化)。这意味着如果没有用户提供外部通用散列函数系列,则无法构建依赖于通用散列的散列表。
最初我认为我可以通过直接对对象的hashCode
应用通用哈希函数来解决这个问题,但这不起作用,因为如果两个对象具有相同的hashCode
,那么< em>您应用于这些哈希码的任何确定性函数,即使是随机选择的哈希函数,也会产生相同的值,从而导致冲突。
这似乎对Java的设计有害。这意味着HashMap
和其他哈希容器完全禁止使用基于通用哈希的表,即使语言设计者可能认为这样的表适合语言设计。这也使第三方库设计者更难以构建这种类型的哈希表。
我的问题是:有没有理由认为Java选择设计hashCode
而没有考虑使用多个哈希函数散列对象的可能性?我理解许多好的哈希方案,如链式哈希或二次探测不需要它,但似乎这个决定使得在Java对象上使用某些类算法变得困难。
答案 0 :(得分:15)
<强>简单即可。 Java允许类设计者提供他们自己的hashCode
,正如你所提到的那样,它对于“普通”哈希表是足够好的,并且可以hard enough来理解。
此外,在设计Java Collections API时,标准库中的通用哈希表已经足够大胆了。 C从来没有过它们。 C ++在STL中将它们作为hash_set
和hash_map
,但那些没有成为标准。直到现在,在C ++ 0x中,哈希表才被考虑再次进行标准化。
答案 1 :(得分:0)
我认为正常的hashCode
方法是在没有“恶意输入”的情况下创建的。此外,正如larsmann所写,它的契约比通用哈希函数更容易理解和实现。
这里有关于该怎么做的想法: