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