【发布时间】:2011-02-01 15:17:47
【问题描述】:
Java 的 ArrayList 会在需要时动态扩展自身。扩展发生时它添加了多少元素?
它是将旧数组复制到新数组中,还是以某种方式将两者联系在一起?
【问题讨论】:
Java 的 ArrayList 会在需要时动态扩展自身。扩展发生时它添加了多少元素?
它是将旧数组复制到新数组中,还是以某种方式将两者联系在一起?
【问题讨论】:
看看source code:
int newCapacity = (oldCapacity * 3)/2 + 1;
具体的因子因实现而异,gnu 使用因子 2。没关系,只是用内存换速度。
它将所有元素复制到一个新数组中。
【讨论】:
它创建一个新的 double 数组,该数组是大小的倍数,并将元素复制过来。 (我不确定实际乘数是否根据 Java 标准指定。)
现在很自然的问题是,为什么?为什么不每次都添加五个元素?
这是为了让事情变得更快:您免费添加 n 元素,并且在元素 n + 1 上,您必须复制 n 将前面的元素放入大小为 2n 的数组中。因此,复制这些 n 元素的成本会分散(“摊销”)到它们自身上(因为您之前免费添加了它们),所以平均而言,添加每个元素的成本是 n /n,或者每个元素大约 1 次操作。
(有关此主题的更多讨论,请参阅this link。)
【讨论】:
严格来说,确切的调整大小行为是not specified in the spec/JavaDoc:
除了添加一个元素具有恒定的摊销时间成本这一事实之外,没有指定增长策略的细节。
这意味着内部数组不能通过添加一个常数来调整大小,但必须涉及一些乘法。正如 maartinus 所指出的,Sun JDK 和 OpenJDK 将大小乘以 1.5(大约)。
【讨论】: