我知道的哈希结构 - HashTable,HashSet& HashMap中。
他们都使用桶结构 - 即两个哈希码是相似 完全相同一个元素不会覆盖另一个,而是将它们放在同一个桶中与该哈希码相关联?
答案 0 :(得分:8)
在Sun当前的Java库实现中,IdentityHashMap
和ThreadLocal
中的内部实现使用探测结构。
在Java中探测哈希表的一般问题是hashCode
和equals
可能相对昂贵。因此,您希望缓存哈希值。你不能有一个混合引用和基元的数组,所以你需要做一些相对复杂的事情。另一方面,如果您使用==
来检查匹配项,那么您可以在没有性能问题的情况下检查许多引用。
答案 1 :(得分:6)
在每个存储桶中使用链接列表来处理散列冲突。请注意, java HashSet
实际上是由下面的HashMap
实现的(所有键都映射到所有HashSet
的相同单例值),因此使用相同的桶结构。
如果添加了一个元素,则在最后添加元素之前,会针对链接列表中的所有项目(通过.equals
)检查其相等性。因此,哈希冲突特别糟糕,因为当链表变大时,这可能是一项昂贵的检查。
答案 2 :(得分:5)
我相信Java哈希结构在执行散列时都使用一种链接形式来处理冒号 - 这会将具有相同散列的项放入列表中。
我不相信Java使用开放式寻址来获取基于散列的数据结构(开放式寻址会重新计算基于重试序列的哈希,直到它在表中找到一个开放的切口)
答案 3 :(得分:4)
否 - open addressing是表示哈希表的替代方法,其中对象直接存储在表中,而不是驻留在链表中。在给定的索引处只能存储一个对象,因此解决冲突会更复杂。
当添加另一个对象已经驻留在同一索引处的对象时,将使用探测序列来确定存储新对象的新索引。删除对象也更复杂,因为如果你删除一个对象,你需要留下一个标记,上面写着“曾经有一个对象在这里”;有关详细信息,请参阅维基百科。
当对象存储为较小且很少被删除时,最好使用开放寻址。开放式寻址提高了缓存性能,因为您不需要通过链接列表的额外级别的间接访问。
您提到的类HashTable
,HashSet
和HashMap
不使用开放式寻址,但您可以轻松创建实现开放式寻址的新类并提供相同的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。根据定义,设置唯一元素。
这是一个错误。请参阅以下评论。