java中所有基于Hash的数据结构都使用“桶”概念吗?

时间:2009-11-24 17:36:54

标签: java hashtable hashmap hashcode data-structures

我知道的哈希结构 - HashTable,HashSet& HashMap中。

他们都使用桶结构 - 即两个哈希码是相似 完全相同一个元素不会覆盖另一个,而是将它们放在同一个桶中与该哈希码相关联?

7 个答案:

答案 0 :(得分:8)

在Sun当前的Java库实现中,IdentityHashMapThreadLocal中的内部实现使用探测结构。

在Java中探测哈希表的一般问题是hashCodeequals可能相对昂贵。因此,您希望缓存哈希值。你不能有一个混合引用和基元的数组,所以你需要做一些相对复杂的事情。另一方面,如果您使用==来检查匹配项,那么您可以在没有性能问题的情况下检查许多引用。

IIRC,Azul有一个快速并发的二次探测哈希映射。

答案 1 :(得分:6)

在每个存储桶中使用链接列表来处理散列冲突。请注意, java HashSet实际上是由下面的HashMap实现的(所有键都映射到所有HashSet的相同单例值),因此使用相同的桶结构。

如果添加了一个元素,则在最后添加元素之前,会针对链接列表中的所有项目(通过.equals)检查其相等性。因此,哈希冲突特别糟糕,因为当链表变大时,这可能是一项昂贵的检查。

答案 2 :(得分:5)

我相信Java哈希结构在执行散列时都使用一种链接形式来处理冒号 - 这会将具有相同散列的项放入列表中。

我不相信Java使用开放式寻址来获取基于散列的数据结构(开放式寻址会重新计算基于重试序列的哈希,直到它在表中找到一个开放的切口)

答案 3 :(得分:4)

否 - open addressing是表示哈希表的替代方法,其中对象直接存储在表中,而不是驻留在链表中。在给定的索引处只能存储一个对象,因此解决冲突会更复杂。

当添加另一个对象已经驻留在同一索引处的对象时,将使用探测序列来确定存储新对象的新索引。删除对象也更复杂,因为如果你删除一个对象,你需要留下一个标记,上面写着“曾经有一个对象在这里”;有关详细信息,请参阅维基百科。

当对象存储为较小且很少被删除时,最好使用开放寻址。开放式寻址提高了缓存性能,因为您不需要通过链接列表的额外级别的间接访问。

您提到的类HashTableHashSetHashMap不使用开放式寻址,但您可以轻松创建实现开放式寻址的新类并提供相同的API作为那些课程。

答案 4 :(得分:2)

apis定义行为,管理Hash冲突的内部结构不会影响API的保证......糟糕的哈希值计算的性能影响是另一个故事。让我们将所有内容哈希到42并查看它的行为。

答案 5 :(得分:0)

Maps和Sets是确定HashSet或HashMap行为的接口。 HashSet是一个Set,因此它的行为类似于Set(即不允许重复)。 HashMap的行为类似于Map - 它不会使用类似的哈希码覆盖密钥,但如果再次使用相同的密钥,它将覆盖密钥。无论在内部支持Map的数据结构如何,这都是相同的。有关详情,请参阅javadoc for Sets和HashMaps。

您是否想要询问其中一种结构的具体实施?

答案 6 :(得分:-3)

除了HashSet。根据定义,设置唯一元素。

这是一个错误。请参阅以下评论。