Java:ArrayList add()和remove()性能,实现?

时间:2011-10-26 23:50:47

标签: java performance collections arraylist

我已经读过某个地方,ArrayList的 add() remove()操作在“分摊的常量”时间内运行。这究竟意味着什么?

add(item)的实现中,我可以看到它ArrayList使用的数组缓冲区最多只有list't大小的3/2,如果它已满,<调用em> System.arraycopy(),它应该在O(n)中执行,而不是O(1)时间。那么System.arraycopy是否尝试做一些比将元素逐个复制到新创建的数组更聪明的事情,因为时间实际上是O(1)?


结论: add(item)以分摊的常量时间运行,但添加(项目,索引)删除(索引) don' t,它们以线性时间运行(如答案中所述)。

6 个答案:

答案 0 :(得分:7)

  

我已经读过某个地方,ArrayList的add()和remove()操作在“amortized constant”时间内运行。

除非在特殊条件下,我认为remove()不是这样。

  • remove(Object)对随机元素的调用平均需要在列表中的一半条目上调用equals,然后复制另一半的引用。

    < / LI>
  • 平均remove(int)调用一个随机元素必须复制一半元素的引用。

remove(...)平均O(1)(例如摊销)的唯一情况是当您使用remove(int)从列表末尾删除一些常量偏移的元素时。

答案 1 :(得分:3)

“摊销”大致意味着“在整个运行时间内平均”。是的,数组副本将是O(n)。但这只会在列表已满时发生,这种情况会发生在n次中。

答案 2 :(得分:0)

我认为,摊销的常数时间只是意味着如果你做大量的操作,它几乎是恒定的时间。因此,在一个测试中,一百万个项目列表,然后在另一个测试中添加两百万个项目到列表中。后者应比前者慢约2倍,因此,摊销时间不变。

答案 3 :(得分:0)

摊销的常数时间与常数时间不同。

基本上分摊的O(1)表示在n次操作中,任何操作的平均运行时间为O(1)。

对于数组列表,它的工作方式如下:

(O(1)insert + O(1)insert + ... + O(n)array copy)/ n operations = O(1)

答案 4 :(得分:0)

深入描述线程Constant Amortized Time

中的分摊常数的含义

答案 5 :(得分:0)

摊销时间用简单的术语解释:

如果你做了一百万次的操作,你并不真正关心那个操作的最坏情况或最好的情况 - 你关心的是你重复操作时需要多少时间一百万次。

因此,如果操作偶尔非常缓慢并不重要,只要“偶尔”很少,以至于慢速被稀释掉。基本上摊还的时间意味着“如果你做很多操作,每次操作需要的平均时间”。摊销时间不必保持不变;你可以有线性和对数的摊销时间或其他任何东西。

让我们采用垫子的动态数组示例,您可以重复添加新项目。通常添加项目需要恒定的时间(即O(1))。但是每次数组都满了,你会分配两倍的空间,将数据复制到新区域,并释放旧空间。假设分配和释放在恒定时间内运行,这个放大过程需要O(n)时间,其中n是数组的当前大小。

所以每次放大时,你花费的时间大约是最后一次放大的两倍。但是你在做这件事之前也等了两倍!因此,每次放大的成本可以在插入中“展开”。这意味着从长远来看,将m个项目添加到数组所需的总时间为O(m),因此摊销时间(即每次插入的时间)为O(1)。