Hashmap如何识别此存储桶已满,并且需要重新哈希,因为如果两个哈希码相同,它将存储在链表中的值,那么据我的理解,此链表没有任何固定大小,可以存储尽可能多的元素可以使这个存储桶永远不会装满,然后如何识别需要重新哈希处理?
答案 0 :(得分:0)
Hashmap在将数据插入和中时保持O(1)的复杂性 从哈希图中获取数据,但对于第13个键值对,则放置请求 将不再是O(1),因为一旦地图意识到第13个 元素进来,即地图的75%被填充。
它将首先使存储桶(阵列)的容量增加一倍,然后将 进行重新哈希处理。重新哈希处理需要重新计算已放置的哈希码 再次将12个键值对放入新索引,这需要 时间。
答案 1 :(得分:0)
在ConcurrentHashMap
中,当发生冲突(即两个不同的键具有相同的哈希)时,实际上是使用一棵红黑树(用于大量元素)或一个链表(用于少量元素)码)。但是您说的对,链接列表(或红黑树)可以无限增长(假设您具有无限的内存和堆大小)。
HashMap
或ConcurrentHashMap
的基本思想是,您希望基于 O(1)时间复杂度的键来检索值。但是实际上,确实会发生冲突,当发生冲突时,我们将节点放在链接到存储桶(或数组单元)的树中。因此,Java可以创建一个HashMap
,其中数组大小将保持固定,并且永远不会进行哈希处理,但是如果这样做,则所有键值都必须容纳在固定大小的数组中(以及它们的链接树) 。
假设您有一种HashMap
,其中数组大小固定为16,并在其中推入1000个键值对。在这种情况下,您最多可以有16个不同的哈希码。反过来,这意味着您将在所有(1000-16)put
中发生冲突,这些新节点将最终出现在树中,并且无法再以O(1)时间复杂性来获取它们。在树中,您需要O(log n)时间来搜索密钥。
为确保不会发生这种情况,HashMap
使用负载因子计算来确定键值对填充了数组的多少。如果已满75%(默认设置),则任何新的put
都会创建一个更大的新数组,将现有内容复制到其中,从而具有更多的存储桶或哈希码空间。这样可以确保在大多数情况下不会发生冲突并且不需要树,并且您会在O(1)时间内获取大多数键。