为什么ArrayList的默认容量是10?

37

我看到了ArrayList的Java文档,发现它的初始容量是10。

 /**
 * Constructs an empty list with an initial capacity of ten.
 */
public ArrayList() {
this(10);
}

我认为如果它是2的任意次幂,则会很有意义,但为什么是10?

我还检查了HashMap的初始容量,它是16,这是有道理的。

/**
 * The default initial capacity - MUST be a power of two.
 */
static final int DEFAULT_INITIAL_CAPACITY = 16;

/**
 * Constructs an empty <tt>HashMap</tt> with the default initial capacity
 * (16) and the default load factor (0.75).
 */
public HashMap() {
    this.loadFactor = DEFAULT_LOAD_FACTOR;
    threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);
    table = new Entry[DEFAULT_INITIAL_CAPACITY];
    init();
}

数字10背后是否有特定的原因?


16
“如果这个数字是2的任何次幂,那么这个说法可能有意义。”为什么呢? - Op De Cirkel
6
我认为这可以追溯到计算机科学中占主导地位的生命形式,它们似乎有两个具有5个数字的操纵器。在计算机早期,这些被用于计数。因此,他们喜欢使用10的幂来处理各种事情。 - Jens Schauder
5
10是数组列表的初始容量,而不是大小。初始大小始终为0。 - BOSS
@AbhisekBose:是的,你说得对。我的错误。应该是容量而不是大小。我修改了问题。 :) - Priyank Doshi
我认为任何2的幂次方数都比任意随机数更好。我不确切知道它比其他任何数字更合适,我认为可能有一个特定的原因,但使用10作为初始容量可能只是因为它既不太大也不太小。 - Priyank Doshi
2
在 Java 1.7.0_40 更新后,ArrayList 的初始容量为0(指向空数组)。 - Ankit Sharma
7个回答

42

ArrayList是一个简单的动态数组。当尝试添加元素时,如果超过了缓冲区大小,它会自动增长。因此,初始大小可以是任何正值。

1太小了。即使只有几个元素,也需要进行几次重新调整大小操作。

100的话则浪费空间。

因此,10是一种妥协。为什么不是12或8?首先,典型的用例被分析过了,这是性能损失和空间浪费之间的最佳折中。然而,我认为,看到Sun的原始代码,它并没有被深入分析,只是一个任意的“既不太小,也不太大”的数字。


13

对于列表来说,容量为2的幂并没有什么优势。实际上,任何特定的起始容量都没有真正的优势。它必须足够大,以避免在小列表的常见情况下进行多次调整大小操作,并且不能在相同情况下浪费未使用的容量。选择10可能只是因为它在正确的范围内满足这些要求,并且因为它是“圆形”的。


1
即使是2的幂次方,也可能没有任何特定容量的真正优势。但是,如果Sun开发人员已经对大量场景进行了足够的分析以找出任何数字,他们应该至少分享它,可能不在Java文档中,而是在任何官方博客中。这样,开源社区中的每个人都有一个想法,其他程序员可以表达他们的观点,使这个初始容量数字更相关于实际开发用例。 - Priyank Doshi
3
@Priyank Doshi: 理想的初始容量因应用而异,因此在大量场景的平均值实际上并不是非常有用——对于大多数应用程序来说,确切的值极不可能有所影响,但对于那些确实会产生影响的应用程序,您将希望使用该特定应用程序的最佳值,而不是某个平均值。 - Michael Borgwardt
2
@PriyankDoshi:几乎可以肯定的答案是,这并不重要到值得大惊小怪。10或多或少已经足够小了,如果它是一个过高的估计,那么也不会有太大的影响,但是更大的ArrayList将相对快速地被调整大小;担心像确切容量这样的细节只是过度杀伤力。 - Louis Wasserman
1
通常在计算机编程算法中,当你处理内存分配等问题时,2的幂次方数是首选。所以我想到了这个。 - Priyank Doshi
1
Java的内存分配与许多其他语言不同——包括垃圾回收、对象头等等。最好不要过于关注类似“二次幂”和“对齐问题”之类的事情。 - Louis Wasserman

10

Vector是JDK 1.0中的一个类,其默认初始容量为10,因此在引入JDK 1.2中的ArrayList时保持一致可能是有道理的。


不行。那将是不兼容的更改。Javadoc,也就是规范,说默认容量是10,所以他们不能随意更改它。 - Thilo
3
我的意思是,他们可能希望ArrayList保持与Vector一致,因为它们密切相关。这并不涉及其他集合实现。 - Denham Coote

5
完全是任意选择。
在这里使用2的次幂没有任何理由。在HashMap中,由于哈希处理方式的原因,使用2的次幂是有道理的。事实上,根据源代码中的注释,它必须是2的次幂。
请注意,java.util.Vector(ArrayList的前身)也有10。

是的,它也有。这也可能是ArrayList容量的原因。但问题是,为什么向量的初始容量是10? - Priyank Doshi

1

10 可能是默认元素数量的一个或多个任意数字。


1
我不认为Sun的开发人员会因为没想好就随意使用任意数字作为默认数字而疯狂。他们一定考虑过某些有用和高效的情况。 - Priyank Doshi

0

ArrayList只是一个可以自动增长的数组。

是的..默认大小为10

我认为在这个初始/默认值背后没有太多的思考。默认值10似乎既不太大也不太小。(也许这就是原因)。如果超过了数组的默认初始容量怎么办呢?下一个数组容量的计算方法是-

New capacity=(current capacity*3)/2+1
So next size would be (10*3)/2+1= 16
And next (16*3)/2+1= 25
And So on...

0

除非代码中有注释,否则我们永远不会确定。然而,我想在某个时候,Sun的工程师已经收集了大量真实应用程序上的ArrayList使用统计数据,并通过实证确定...最佳结果平均值大约为10。(这就是它们调整这些东西的方式,优化器、字节码设计等等。)

正如其他人指出的那样,对于ArrayList的大小使用2的幂次方大小没有计算上的优势或劣势。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接