ArrayList初始容量介绍?
在Java中,ArrayList的初始容量是10。这个容量是通过DEFAULT_CAPACITY常量定义的,默认值为10。你可以在 ArrayList 类的源码中找到这个定义。如下所示
/**
* Default initial capacity.
*/
private static final int DEFAULT_CAPACITY = 10;
为什么选择初始容量为 10 呢?个人认为这涉及到ArrayList内部的实现机制以及性能考虑,有如下几个方面的原因。
- 初始容量为 10 的选择是为了在大多数情况下能够满足一般的需求,同时尽可能减少扩容的次数。如果初始容量过小,可能会导致在插入大量元素时频繁扩容,影响性能。
- 初始容量为 10 也是一种折衷考虑,既不会过度占用内存,又能够满足大部分场景的需求。如果初始容量过大,会导致在数据量较小的情况下浪费内存空间。
- 初始容量为 10 在 JDK 的设计中是一种经验值,经过实践验证能够满足绝大多数情况下的需求。对于特定的场景,开发者可以根据实际情况手动调整初始容量。
总的来说,初始容量为 10 是一种在性能和内存消耗之间的折中选择,能够在大多数情况下提供较好的性能表现。如果在实际使用中发现需要更大或更小的初始容量,可以根据具体需求进行调整。
ArrayList的扩容机制
ArrayList的扩容机制主要涉及到ensureCapacityInternal()方法和grow()方法。让我们来详细介绍一下这两个方法以及它们的扩容机制。
ensureCapacityInternal()方法
ensureCapacityInternal()方法用于确保ArrayList内部的容量至少能够容纳指定数量的元素。当向ArrayList中添加元素时,如果当前容量不足以容纳新增元素,就会触发扩容操作。这个方法的实现如下。
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
这个方法首先检查elementData是否为默认的空数组(DEFAULTCAPACITY_EMPTY_ELEMENTDATA),如果是的话,将当前容量和默认容量(DEFAULT_CAPACITY)中的较大值赋给minCapacity。然后调用ensureExplicitCapacity()方法来确保容量的扩充。
grow() 方法
grow()方法用于实际进行容量的扩充操作。当需要扩容时ArrayList会创建一个新的数组,并将原数组中的元素复制到新数组中。这个方法的实现如下。
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
这个方法首先计算新的容量newCapacity,这里使用了位运算来将原容量的一半加到原容量上,即oldCapacity + (oldCapacity >> 1)。然后判断新容量是否足够容纳新增元素,如果不够,则将minCapacity设置为新的容量。接着检查是否超出了数组最大容量限制MAX_ARRAY_SIZE,如果超出了,则调用hugeCapacity()方法进行处理。最后,使用Arrays.copyOf()方法创建一个新的数组,并将原数组中的元素复制到新数组中。
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
hugeCapacity()方法用于处理超出数组最大容量限制的情况,如果超出了限制,就会抛出OutOfMemoryError异常。否则,返回MAX_ARRAY_SIZE(Integer.MAX_VALUE - 8)。
总结
通过以上介绍,我们可以看到ArrayList的扩容机制是通过在需要扩容时创建一个新数组,并将原数组中的元素复制到新数组中来实现的。扩容时新容量的计算采用了一种简单的算法,即将原容量的一半加到原容量上,这样可以在大多数情况下有效地减少扩容次数。