如何选择正确的List实现?

时间:2016-02-13 03:16:44

标签: java performance list

来自this CodeReview answer

  

您似乎将ArrayList用于所有目的。 Java中还有其他List类型比ArrayList更适合某些情况。您应该看看这些并尝试了解何时使用哪个列表。在这个特殊情况下,i.E。 LinkedList更好。

我也倾向于大量使用ArrayList,并且没有看到选择其他列表类型背后的逻辑。

List docs显示五个主要List子类:ArrayListCopyOnWriteArrayListLinkedListStackVector

来自ArrayList文档,

  

size,isEmpty,get,set,iterator和listIterator操作以恒定时间运行。添加操作以分摊的常量时间运行,即添加n个元素需要O(n)时间。所有其他操作都以线性时间运行(粗略地说)。与LinkedList实现相比,常数因子较低。

这表明ArrayList通常会优于LinkedList(由this heavily upvoted question支持的断言),尽管LinkedList文档并不能很好地了解效果:

  

所有操作都可以按照预期的方式执行双向链接列表。

CopyOnWriteArrayList对于不变的列表似乎有用,因为每次修改的完整快照对于正常使用而言似乎都非常昂贵。

即使Stack文档也不建议使用它:

  

Deque接口及其实现提供了一套更完整,更一致的LIFO堆栈操作,应优先使用该类。

由于Vector已同步且其余List子类未同步,因此在我看来Vector将是线程安全环境中的最佳选择。

然而,即使阅读了文档,我仍然不认为我理解两个答案的来源。 CopyOnWriteArrayListVector每个似乎都有一个专门的用例,Stack似乎不值得使用,ArrayList似乎优于LinkedList。< / p>

我在这里缺少什么,在什么情况下,另一个List实施优于ArrayList

2 个答案:

答案 0 :(得分:0)

简单地说,你是对的,在这种特殊情况下,TwoThe是不正确的。正如您所指出的那样,由于您在此处所做的只是Return和循环,add只会减慢您的速度。这是LinkedList完全有效的用例,如果您不确定使用哪个ArrayList,则默认为ArrayList没有任何问题。

有关何时使用List的更详细说明,this question的答案可能会有所帮助。

答案 1 :(得分:0)

我同意ArrayList是许多用途的正确选择。 LinkedList每个元素使用8或16个字节的内存作为指针,索引是O(长度),如你所说。

那么LinkedLists有什么优势?

  • 在迭代期间使用remove()删除是恒定时间。使用ArrayList,它是O(长度)。
  • 添加新列表节点始终需要相同的时间。当ArrayList空间不足时,会在后台分配更大的内存块,并复制所有内容。虽然每个元素的多次操作的摊销时间是不变的,但个人add()的成本是O(长度)。如果不接受此类定期延迟,则无法使用ArrayList

至于其他人,Vector可以追溯到Java的早期阶段。这是线程安全的。因为这会增加每个操作的成本,所以它的使用或多或少地被弃用,而不是ArrayList。当您需要线程安全时,可以在SynchronizedList周围使用ArrayList包装器。同样地,Stack或多或少地被弃用,以支持更现代而非线程安全的Deque

CopyOnWriteArrayList是一个线程安全数据列表,通过在任何元素更改时随时制作完整数组副本的一些不寻常的措施来获得安全性。虽然这听起来很疯狂,但是如果有许多线程在同一个数组上进行迭代是有意义的,因为更改不必等待迭代全部完成,而其他并发列表通常就是这种情况。