Java 6和Java 7在ArrayList容量增长方面的差异
我有一个关于如何在Java中管理ArrayList的容量增长(不是大小,而是容量)的问题。 当我们使用默认构造函数初始化ArrayList而不设置容量时,默认情况下容量设置为=10 此时,当我们将另一个元素添加到列表中时,Oracle文档说“当元素添加到ArrayList中时,其容量会自动增长。除了添加元素具有恒定的摊余时间成本这一事实之外,不会指定增长策略的详细信息。” 如果我们看看Java内部,容量增长策略已经改变了它的功能。在Java 6之前,它是:Java 6和Java 7在ArrayList容量增长方面的差异,java,math,arraylist,Java,Math,Arraylist,我有一个关于如何在Java中管理ArrayList的容量增长(不是大小,而是容量)的问题。 当我们使用默认构造函数初始化ArrayList而不设置容量时,默认情况下容量设置为=10 此时,当我们将另一个元素添加到列表中时,Oracle文档说“当元素添加到ArrayList中时,其容量会自动增长。除了添加元素具有恒定的摊余时间成本这一事实之外,不会指定增长策略的详细信息。” 如果我们看看Java内部,容量增长策略已经改变了它的功能。在Java 6之前,它是: (1) int newCapacity
(1) int newCapacity = (oldCapacity * 3)/2 + 1;
从Java 7(和>7)可以看出:
但这两个数学级数略有不同。从默认值(10)开始,我们有:
(1) 10,16,25,38,58,88133200301452
(2) 10,15,22,33,49,73109163244366
我认为这对ArrayList的使用没有任何影响,但是为什么他们要更改这个函数呢?是否存在任何性能原因?他们是否在旧版本中发现了一个缺陷或bug?OpenJDK显示,它已被in更改以修复bug
新代码小心地避免了不必要的整数溢出<代码>旧容量*3可以溢出,即使旧容量*3/2
没有溢出。新行oldCapacity+(oldCapacity>>1)
将不起作用。如果它确实溢出并变为负值,则会有额外的代码将容量设置为Integer.MAX_VALUE
(或接近它)
值得注意的是,关于摊销时间的任何陈述
添加/插入操作的复杂性,例如ArrayList中的操作
javadoc,由于与性能相关的bug而失效。一个
解决上述情况的方法是设置
初始大小计算时,将数组备份为整数.MAX_值
在调整大小期间,结果为负数
(2) int newCapacity = oldCapacity + (oldCapacity >> 1);
/**
* The maximum size of array to allocate.
* Some VMs reserve some header words in an array.
* Attempts to allocate larger arrays may result in
* OutOfMemoryError: Requested array size exceeds VM limit
*/
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
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);
}
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
int newCapacity = (oldCapacity * 3)/2 + 1;
if (newCapacity < minCapacity)
newCapacity = minCapacity;