【发布时间】:2022-01-13 15:19:30
【问题描述】:
它在调用ArrayList.add()后删除列表中多余的未使用位置
但是为什么在 ArrayList 类中没有自动调用呢?
【问题讨论】:
-
因为当你添加另一个东西时,你必须再次放大列表。 ArrayList 已摊销线性插入时间,因为它不必每次添加到列表时都调整列表大小。
它在调用ArrayList.add()后删除列表中多余的未使用位置
但是为什么在 ArrayList 类中没有自动调用呢?
【问题讨论】:
如果添加时 ArrayList 已满,则必须将其内容复制到一个新的更大的数组中。基本上:
void add(Object newItem) {
if (size == array.length) {
array = Arrays.copyOf(array, newSize);
}
array[size++] = newItem;
}
问题是你如何选择newSize:你显然可以选择一个刚好大到足以容纳新项目的值,即
newSize = size + 1;
但您必须将 size 项复制到新数组中。
如果您以这种方式将 10 项添加到 ArrayList,您将复制 0 项、1 项、2 项、3 项.... 9 项:以这种方式添加的成本是二次方的。
相反,采用不同的策略:将列表的大小增加一些乘法因子,例如2:
* (List size initially 1)
* Add item 1
* Copy array into length-2 array
* Add item 2
* Copy array into length-4 array
* Add item 3
* Add item 4
* Copy array into length-8 array
* Add item 5
* Add item 6
* Add item 7
* Add item 8
* Copy array into length-16 array
* Add item 9
* Add item 10
所以,随着数组变大,你做的副本会越来越少。事实上,数学计算表明,以这种方式添加和调整大小是线性,而不是二次的。
所以,当然,您最终可能会得到一个太大的后备数组;当您完成向其中添加内容时,请务必将其修剪到容量。但在时间方面不是自动修剪它更有效。
【讨论】: