ArrayList 还是 LinkedList 哪个运行得更快? [复制]

Posted

技术标签:

【中文标题】ArrayList 还是 LinkedList 哪个运行得更快? [复制]【英文标题】:Which one runs faster, ArrayList or LinkedList? [duplicate] 【发布时间】:2013-09-15 02:16:43 【问题描述】:
List li = new LinkedList();

for (int i = 0; i < 100; i++) 
    li.add(i);


long start1 = System.nanoTime();
li.get(57);

long end1 = System.nanoTime();
long diff1 = end1-start1;

System.out.println("Time taken by LinkedList = "+diff1);

List al = new ArrayList();
for (int i = 0; i < 100; i++) 
    al.add(i);

无论我对这两个列表执行什么操作,当我打印出所用时间时,ArrayList 总是比 LinkedList 运行得快。 有人可以解释哪个在所花费的时间方面表现更好吗? 如果代码有问题,也请告诉我。谢谢!

【问题讨论】:

你检查***.com/questions/322715/…了吗?此链接是相关问题中的第一个 对于 100 个循环,差异可以忽略不计。尝试 1000 万或更多的循环。 ***.com/questions/322715/… 和 ***.com/questions/10656471/… 的重复项 programcreek.com/2013/03/arraylist-vs-linkedlist-vs-vector javarevisited.blogspot.in/2012/02/… 链接可能对您有所帮助 @VaibhavDesai - 成功了!我增加了要添加到列表中的元素数量,现在我可以看到在 LinkedList 中随机索引处的插入比在 ArrayList 中更好 【参考方案1】:

LinkedList 在添加每个元素时会涉及创建新节点,而它不在数组列表中。

如果你知道初始大小然后在创建时将它传递给ArrayList,它避免了数组的重建 喜欢new ArrayList(100);

【讨论】:

【参考方案2】:

如果您必须执行大量插入和不那么频繁的查找,请使用LinkedList。如果您执行的查找多于插入,请使用ArrayList

原因如下 - ArrayList 由具有初始容量的数组支持。因此,如果您继续向列表中插入项目,则在某一时刻它将不得不重新调整其数组容量以适应新插入的项目,并且如果您执行特定于索引的插入,它可能还必须移动现有项目。另一方面,LinkedList 由链表支持,其中创建项目总是在恒定时间内执行 - 创建一个项目并将其分配到列表的末尾。这里没有重新调整。

现在要从ArrayList 获取一个项目,它总是需要固定的时间,因为它可以很容易地在固定的时间内索引后备数组。但是从LinkedList 中获取项目可能会导致您遍历整个链表以找到项目节点。因此,在这种情况下,它的性能低于ArrayList

从上面的讨论中,您可以看到,当您有更多的插入操作时,LinkedList 将始终优于 ArrayList,因为后者具有与插入相关的内部调整大小成本,而前者没有。另一方面,如果你有不频繁的插入和频繁的查找,ArrayList 将总是优于LinkedList,因为对于后者,你可能必须遍历整个链表结构才能找到所需的项目,而前者将能够使用数组索引在恒定时间内快速找到您的项目。

当您处理大量项目(例如,数千个项目)时,上述所有效果都将可见并影响应用程序的性能。对于较少的项目,性能差异不太明显。

现在,关于您的代码,您遇到了一些严重的问题。首先,您使用的是原始类型,这很糟糕,因为您失去了泛型必须提供的所有类型安全性。编写新代码时,应始终使用通用版本的 Collection API。所以,改变你的代码如下 -

List<Integer> li = new LinkedList<Integer>();
for (int i = 0; i < 100; i++) 
    li.add(i);


long start1 = System.nanoTime();
li.get(57);

long end1 = System.nanoTime();
long diff1 = end1 - start1;

System.out.println("Time taken by LinkedList = "+diff1);

List<Integer> al = new ArrayList<Integer>();
for (int i = 0; i < 100; i++) 
    al.add(i);

请参阅 Effective Java第 23 条:不要在新代码中使用原始类型以获得详细说明。

编辑

从 cmets 的讨论中,你应该很明显,如果你需要在列表的中间或随机位置插入元素,那么 ArrayList 在性能方面优于 LinkedList,因为前者将使用memcpy 移动元素,速度非常快,后者必须遍历到所需的索引才能正确插入新元素,这比较慢。所以对于随机插入ArrayList 也优于LinkedListLinkedList 优于 ArrayList 的唯一情况是您只在列表末尾插入,并且有很多这样的插入。

【讨论】:

“如果您必须执行大量插入和不那么频繁的查找,请使用 LinkedList”我想知道对于大列表末尾附近的插入是否适用。 LinkedList 在插入之前几乎必须遍历整个过程,而 ArrayList 可以依赖 System.arrayCopy() ,它是本机操作并且应该足够快。这里必须有一个神奇的元素数量才能使 ArrayList 更有效(至少在这个特定场景中) @SeanPatrickFloyd: 如果LinkedList 的底层链表是使用double-pointer-strategy 实现的,这意味着如果它保留了链表开始和结束的指针,那么它将不会t 必须遍历整个结构。我见过有人以这种方式实现链表以实现高效插入,内存成本只是一个额外的指针。 @Sayem 也许你误解了我,因为我实际上同意你的观点(我检查了具有双指针策略的 sun 版本,它需要它,因为 LinkedList 实现了 Deque)。 实际上比这更微妙一些。首先,插入到ArrayList 的末尾是在摊销的常数时间内,所以“平均而言”(即,在很多插入中)它将具有与LinkedList 相同的增长。最坏的情况会更慢,但如果您不从事实时 esq 项目(例如,您必须及时完成下一帧的游戏),这可能就没那么有趣了。另外,即使渐近增长较大,您也必须考虑系数; memcpy 非常快。 ArrayList 可能会击败 LinkedList,即使在小列表等的非附加插入中也是如此 @SeanPatrickFloyd:是的,对不起,我在再次阅读 cmets 后明白了:P。【参考方案3】:

ArrayList 由数组支持,LinkedList 支持的节点与引用链接。

所以对ArrayList 的操作实际上是对数组的求值操作。添加操作以摊销的常数时间运行,即添加 n 个元素需要O(n) 时间。所有其他操作都以线性时间运行(粗略地说)。与LinkedList 实现相比,常数因子较低。

LinkedList 上,所有操作都按照双向链表的预期执行。索引到列表中的操作将从开头或结尾遍历列表,以更接近指定索引的为准。

阅读更多文档 -

ArrayList LinkedList

【讨论】:

【参考方案4】:

数组列表在读取方面总是比链表快。 ArrayList 基本上是数组实现,为数组分配的内存是顺序的,因此读取速度更快。但是,当您使用需要在列表之间插入或删除的列表时,链接列表会更快。因为它只需要在节点之间添加链接。这两种情况下数组列表会比较慢。用法可以:

ArrayList - 更快的读取操作,列表之间的插入、删除更慢。 链表 - 读取操作比数组列表慢,但列表之间的插入、删除更快。

【讨论】:

以上是关于ArrayList 还是 LinkedList 哪个运行得更快? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

ArrayList 还是 LinkedList 哪个运行得更快? [复制]

用 ArrayList 还是 LinkedList?看完你就懂了!

用 ArrayList 还是 LinkedList?看完你就懂了!

用 ArrayList 还是 LinkedList?看完你就懂了!

优雅代码13-linkedList插入真的比arrayList快么

ArrayList、LinkedList、HashMap哪个速度更快