我一直是一个简单使用的人:

List<String> names = new ArrayList<>();

我使用接口作为可移植性的类型名称,这样当我问类似这样的问题时,我就可以修改代码。

LinkedList何时应用于ArrayList,反之亦然?


当前回答

您可以根据对该特定列表执行的操作的时间复杂性,使用一个而不是另一个。

|---------------------|---------------------|--------------------|------------|
|      Operation      |     ArrayList       |     LinkedList     |   Winner   |
|---------------------|---------------------|--------------------|------------|
|     get(index)      |       O(1)          |         O(n)       | ArrayList  |
|                     |                     |  n/4 steps in avg  |            |
|---------------------|---------------------|--------------------|------------|
|      add(E)         |       O(1)          |         O(1)       | LinkedList |
|                     |---------------------|--------------------|            |
|                     | O(n) in worst case  |                    |            |
|---------------------|---------------------|--------------------|------------|
|    add(index, E)    |       O(n)          |         O(n)       | LinkedList |
|                     |     n/2 steps       |      n/4 steps     |            |
|                     |---------------------|--------------------|            |
|                     |                     |  O(1) if index = 0 |            |
|---------------------|---------------------|--------------------|------------|
|  remove(index, E)   |       O(n)          |         O(n)       | LinkedList |
|                     |---------------------|--------------------|            |
|                     |     n/2 steps       |      n/4 steps     |            |
|---------------------|---------------------|--------------------|------------|
|  Iterator.remove()  |       O(n)          |         O(1)       | LinkedList |
|  ListIterator.add() |                     |                    |            |
|---------------------|---------------------|--------------------|------------|


|--------------------------------------|-----------------------------------|
|              ArrayList               |            LinkedList             |
|--------------------------------------|-----------------------------------|
|     Allows fast read access          |   Retrieving element takes O(n)   |
|--------------------------------------|-----------------------------------|
|   Adding an element require shifting | o(1) [but traversing takes time]  |
|       all the later elements         |                                   |
|--------------------------------------|-----------------------------------|
|   To add more elements than capacity |
|    new array need to be allocated    |
|--------------------------------------|

其他回答

到目前为止,除了人们普遍认为LinkedList比ArrayList“多得多”之外,似乎没有人解决这些列表中每一个的内存占用问题,所以我做了一些数字处理,以证明这两个列表对于N个空引用所占的空间。

由于引用在其相对系统上是32位或64位(即使为空),因此我为32位和64位LinkedList和ArrayList包含了4组数据。

注意:ArrayList行显示的大小是用于修剪列表的-实际上,ArrayList中的后备数组的容量通常大于其当前元素计数。

注2:(感谢BeeOnRope)由于压缩Oops现在是默认值,从JDK6中期开始,以下64位机器的值将基本上与32位机器的对应值相匹配,当然,除非您特意关闭它。



结果清楚地表明,LinkedList比ArrayList多得多,尤其是元素数非常高的情况。如果内存是一个因素,请避开LinkedList。

我使用的公式如下,如果我做错了什么,请告诉我,我会改正的对于32位或64位系统,b’是4或8,而n’是元素的数量。注意mods的原因是因为java中的所有对象都将占用8字节的倍数空间,而不管是否全部使用。

阵列列表:

ArrayList对象头+大小整数+modCount整数+数组引用+(数组项目头+b*n)+MOD

链接列表:

LinkedList对象标头+大小整数+modCount整数+对标头的引用+对页脚的引用+(节点对象开销+对上一元素的引用+下一元素的参考+对元素的引用)*n)+MOD(节点对象,8)*n+MOD, 8)

数组列表本质上是一个具有添加项等方法的数组(您应该使用通用列表)。它是可以通过索引器(例如[0])访问的项的集合。它意味着从一个项目到下一个项目的进展。

链接列表指定从一个项目到下一个项目(项目A->项目b)的进度。您可以使用数组列表获得相同的效果,但链接列表绝对会说明前一个列表后面应该包含哪些项。

如果您的代码有add(0)和remove(0),请使用LinkedList,这是更漂亮的addFirst()和removeFirst()方法。否则,请使用ArrayList。

当然,Guava的ImmutableList是你最好的朋友。

对于ArrayList和LinkedList,remove()和insert()的运行时效率都为O(n)。然而,线性处理时间背后的原因来自两个非常不同的原因:

在ArrayList中,您可以找到O(1)中的元素,但实际上删除或插入某些元素会使其成为O(n),因为以下所有元素都需要更改。

在LinkedList中,实际到达所需元素需要O(n),因为我们必须从一开始就开始,直到达到所需的索引。实际上,移除或插入是常量,因为我们只需要为remove()更改1个引用,为insert()更改2个引用。

插入和删除这两项中的哪一项更快取决于发生的位置。如果我们更接近开始,LinkedList将更快,因为我们必须经过相对较少的元素。如果我们接近末尾,ArrayList将更快,因为我们在恒定的时间内到达那里,只需更改紧随其后的几个剩余元素。如果正好在中间完成,LinkedList将更快速,因为遍历n个元素比移动n个值更快。

好处:虽然无法为ArrayList创建这两个方法O(1),但实际上在LinkedList中有一种方法可以做到这一点。假设我们想在整个列表中删除和插入元素。通常,您可以使用LinkedList从头开始每个元素,我们也可以使用迭代器“保存”当前正在处理的元素。在迭代器的帮助下,当在LinkedList中工作时,remove()和insert()的效率为O(1)。使其成为我所知的唯一性能优势,LinkedList总是优于ArrayList。

ArrayList扩展了AbstractList并实现了List接口。ArrayList是动态数组。可以说,它的创建基本上是为了克服数组的缺点LinkedList类扩展了AbstractSequentialList并实现了List、Deque和Queue接口。表演arraylist.get()是O(1),而linkedlist.getarraylist.add()为O(1),linkedlist.add)为0(1)arraylist.contains()为O(n),linkedlist.contans()为0(n)arraylist.next()为O(1),linkedlist.next()为0(1)arraylist.remove()是O(n),而linkedlist.remove()是0(1)在arraylistiterator.remove()是O(n),而在linkedlist迭代器.remove