为什么Java的hashCode不支持通用散列?

一些散列表方案,例如布谷鸟散列或动态完美散列 ,依赖于通用散列函数的存在以及通过从通用散列函数族中选择新的散列函数来获取展示冲突的数据集合并解决这些冲突的能力。

前一段时间我试图在由cuckoo散列支持的Java中实现哈希表并遇到麻烦,因为虽然所有Java对象都有hashCode函数,但hashCode返回的值对于每个对象都是固定的(当然,除非对象发生变化) )。 这意味着如果没有用户提供外部通用散列函数系列,则无法构建依赖于通用散列的散列表。

最初我认为我可以通过直接对对象的hashCode应用通用哈希函数来解决这个问题,但是这不起作用,因为如果两个对象具有相同的hashCode ,那么你应用于那些哈希码的任何确定性函数,甚至是随机选择的散列函数,将导致相同的值,从而导致冲突。

看起来这对Java的设计是不利的。 这意味着完全禁止HashMap和其他哈希容器使用基于通用哈希的表,即使语言设计者可能认为这些表适合语言设计。 它还使第三方库设计者更难以构建此类哈希表。

我的问题是: 有没有理由认为Java选择设计hashCode而不考虑使用多个哈希函数散列对象的可能性? 我知道许多好的散列方案,如链式散列或二次探测都不需要它,但似乎这个决定使得在Java对象上使用某些类算法变得困难。

简单 。 Java允许类设计者提供他们自己的hashCode ,正如你所提到的那样,它对于“普通”哈希表来说已经足够了,并且可能很难理解。

此外,在设计Java Collections API时,标准库中的通用哈希表已经足够大胆了。 C从来没有过它们。 C ++将它们作为hash_sethash_map放在STL中,但那些并没有成为标准。 直到现在,在C ++ 0x中,哈希表才被再次考虑用于标准化。

我认为正常的hashCode方法是在没有“恶意输入”的情况下创建的。 此外,正如larsmann所写,它的契约比通用哈希函数更容易理解和实现。

这里有一个关于做什么的想法:

  • 使用依赖于外部哈希函数的map实现(比如几小时前我在这里提出的HashableEquivalenceRelation )
  • 然后使用这种实现的通用族(或允许更改参数以切换到该族的另一个成员的实现)。