为什么不同的Java集合具有不同的默认容量?


11

看着不同的集合构造函数,这个问题浮现在脑海。为什么ArrayList()构造一个初始容量为10的空列表,为什么ArrayDeque()构造一个初始容量为足以容纳16个元素的空数组双端队列。


我没有新的容量限制。我只是简单地使用add()添加新元素。它始终有效。
TulainsCórdova'13年

1
我认为他是在谈论ArrayList实现中数组的初始数组大小。顾名思义,ArrayList只是一个隐藏的原始数组,当您尝试添加超出其当前数组大小包含的元素时,它会自动创建更大的数组。
dsw88 2013年

1
我认为StringBuilder是另一个具有默认功能的功能,是10还是16?
Ingo 2013年

@Ingo有趣。我什至不知道收藏之外的东西都与容量有关,但我认为这是有道理的。当时没有容量标签,所以我对其他用途没有太大兴趣。
老巴德曼·格雷(Badman Gray)2013年

Answers:


17

简短答案

因为ArrayDeque容量必须是2的幂,并且16是2的最小幂至少为10。


ArrayDeque到处都需要使用很多%运算来包裹一个假装为圆形的线性数组。

a % b可表现为a & (b - 1) ,如果 b是二的幂。逐位AND运算速度更快,因此ArrayDeque的容量被限制为2的幂。所有%操作均使用位屏蔽而不是实现中的实际%。

这也是为什么较新的HashMap不使用质数表大小而是使用2的幂的原因,这又是因为%操作需要如此频繁地按位执行,并且速度要快得多。

因此,如果基线为10,则具有两个限制的幂的结构应使用16,因为它是两个的最小幂至少为10。


3

不要排除没有特定原因的可能性。

这两个集合可能是由不同的团队撰写的。两者都选择了一个较小的数字作为默认容量,但是第一个团队以小数点的形式考虑并选择10,而第二个团队以二进制的形式来选择16。


1

@Esailija的回答对于此特定情况很好。

不过,更一般而言,这是一个折衷方案,取决于许多因素。我举几个例子:

  • 通常如何使用数据结构?例如,用作数据缓冲区的数据结构通常会比用于小元组的数据结构更喜欢容量。
  • 目标CPU平台上的高速缓存行中适合什么默认数据大小?如果默认值适合高速缓存行,则会对性能产生很大影响。选择10作为Java中的默认设置很可能是因为10个32位字的数组加上数组/对象开销适合于64字节高速缓存行。
  • 对空间与运行时效率有何评价?如果想要更好的运行时性能,通常最好预先分配更多的空间,以避免以后再进行额外的分配。

这些折衷的结果是完全可以理解的是,不同的收集实现可能具有不同的最佳默认容量。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.