为什么ArrayList以1.5的速度增长,但对于Hashmap来说,它是2?

2022-09-02 20:29:28

根据Sun Java实现,在扩展期间,ArrayList的初始容量增长到3/2,而对于HashMap,扩展速率是两倍。这背后的原因是什么?

根据实现,对于HashMap,容量应始终处于两者的幂中。这可能是HashMap行为的一个原因。但在这种情况下,问题是,对于HashMap来说,为什么容量应该总是由两个组成?


答案 1

增加 ArrayList 容量的昂贵部分是将支持阵列的内容复制到一个新的(更大的)支持阵列。

对于 HashMap,它正在创建一个新的支持数组,并将所有映射条目放在新数组中。而且,容量越高,碰撞风险越低。这更昂贵,并解释了为什么膨胀系数更高。1.5与2.0的原因是什么?我认为这是“最佳实践”或“良好的权衡”。


答案 2

对于HashMap,为什么容量应该总是在两个的幂上?

我能想到两个原因。

  1. 您可以快速确定哈希码进入的存储桶。你只需要一个按位和,没有昂贵的模。int bucket = hashcode & (size-1);

  2. 假设我们的增长因子为 1.7。如果我们从大小 11 开始,则下一个大小将是 18,然后是 31。没关系。右?但是Java中字符串的哈希码是用31的质因数计算的。然后,字符串进入的存储桶仅由字符串的最后一个字符确定。再见,如果您存储的文件夹都以 结尾。例如,如果使用 的大小,则如果增加 n,分布不会变得更糟。从大小到 ,桶中的每个元素现在都会转到 bucket ,或者 ,这取决于更高的数字。这就像把每个桶分成三块。因此,整数增长因子的大小将是首选。(当然,这一切都取决于你如何计算哈希码,但任意增长因子感觉并不“稳定”。hashcode%31O(1)/3^n392257