HashMap
以非常简单的方式实现,但它需要一个天才才能理解它是如何实现的。所以,我在java docs中读到了HashMap
。关于HashMap
,我有一些小问题:
HashMap
的默认容量为16.在java docs中,他们给出了默认的初始容量 - 必须是2的幂。。这背后的具体原因是什么?HashMap
如何在HashCode,Bucket和LinkedList
的基础上工作,如果我没有错的话。那么HashMap
的大小是如何增加的。我的意思是如何管理存储桶大小和LinkedList大小。HashMap
中添加新元素时,基于HashCode,它可以直接访问该特定存储桶而无需像LinkedList
那样移动。我对吗?而另一件事是它在头部添加元素而不是尾部。这是什么原因。是否在存储桶内的LinkedList
的头部添加了新元素以避免尾部遍历。我的想法是否正确? 答案 0 :(得分:2)
使用2的幂可以简化实施并提高其性能 例如。要从哈希码中找到一个桶,它可以使用哈希& (SIZE -1)代替abs(哈希)%SIZE
在您知道HashMap
如何正常工作之前,您将无法回答此问题。如果Map的大小超过由load-factor定义的给定阈值,例如如果载荷系数是.75,一旦填充了75%,它将重新调整地图的大小。与ArrayList
等其他集合类似,Java HashMap
通过创建一个大小为HashMap
之前大小两倍的新桶数组来重新调整自身大小,然后开始将每个旧元素放入其中新的桶阵列。此过程称为rehashing,因为它还应用散列函数来查找新的存储桶位置。
我们将每个新元素存储在链表的头部以避免尾部遍历,因此在调整链接列表中的整个对象序列时,它们会被反转,在此期间可能存在无限循环。 / p>
在这里阅读更多内容:
答案 1 :(得分:2)
使容量为2的能力的原因(我认为)主要是为了简化代码。有一个小的性能优势,但它几乎可以忽略不计。
它是这样的:
当您尝试添加新条目时,会扩展HashMap。它(大致说来)发生在map.size() * load_factor > array.length
时。 (有关详细信息,请参阅代码。)
扩展HashMap时,数组的大小加倍。有一个硬限制......由Java中的数组大小强加。之后,HasMap的数组不会扩展。 (相反,你只需要更长和更长的哈希链......)
没有做任何事情来管理各个哈希链的长度。相反,当HashMap扩展时,每个旧链中的条目将移动到扩展表中的相应链。 (至少在最近的实现中,每个链节点都保存了条目的缓存哈希值,因此在表扩展期间无需重新评估哈希函数。)
基本上,是的,是的。新条目被添加到每个哈希链的开头,因为这是最有效的(时间和空间)。由于哈希链中元素的顺序不表示任何内容,因此在链的尾部插入新条目没有意义。这也意味着在典型的HashMap实现中,扩展表会反转哈希链条目的顺序。
请注意,HashMap
的实际行为和实际实现细节因Java的不同版本而异。唯一可以确定的方法是阅读您正在使用的Java版本的源代码。
答案 2 :(得分:0)
我认为两个要求的力量就是加速挑选桶。如果您有16个桶,索引为578123或其他东西,您可以使用简单的AND来选择一个桶,而不必计算578123 mod 16,这个速度较慢。
HashMap
有一个加载因子,默认为0.75。如果对象的数量>桶数量*加载因子,HashMap的容量增加以保持性能。我认为它只是将桶的数量加倍并重新分配所有元素。
抱歉,我不确定我是否理解这个问题。