问题 哪一个运行得更快,ArrayList或LinkedList? [重复]


这个问题在这里已有答案:


4293
2017-09-11 07:02


起源

你检查了吗 stackoverflow.com/questions/322715/... ?此链接是相关问题中的第一个 - Nandkumar Tekale
对于100的循环,差异可以忽略不计。尝试1000万或更多的循环。 - Vaibhav Desai
重复的 stackoverflow.com/questions/322715/... 和 stackoverflow.com/questions/10656471/... - Jules
programcreek.com/2013/03/arraylist-vs-linkedlist-vs-vector  javarevisited.blogspot.in/2012/02/... 链接可能会帮助你 - Jayaram
@VaibhavDesai - 那很有效!我增加了要添加到列表中的元素数量,现在我可以看到在LinkedList中的随机索引插入比在ArrayList中更好 - Anjan Baradwaj


答案:


如果你必须执行大量的插入和不频繁的查找,请使用a 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);
}

看到 有效的Java第23项:不要在新代码中使用原始类型 详细解释。

编辑

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


14
2017-09-11 07:05



“如果你必须执行大量的插入和不那么频繁的查找,请使用LinkedList”我想知道对于大型列表末尾附近的插入是否正确。 LinkedList必须在插入之前几乎遍历整个方式,而ArrayList可以依赖System.arrayCopy(),这是一个本机操作,应该足够快。这里必须有一个神奇的阈值数量的元素,使ArrayList更有效(至少在这个特定的场景中) - Sean Patrick Floyd
@SeanPatrickFloyd:如果是底层的链表 LinkedList 使用a实现 double-pointer-strategy,这意味着如果它保持链表的开始和结束的指针,那么它将不必遍历整个结构。我已经看到人们以这种方式实现链表以便有效插入,内存成本只是一个额外的指针。 - MD Sayem Ahmed
这正是java.util.LinkedList所做的(只是检查了代码)。我有所纠正。或者更确切地说:现在插入中间附近是极端情况:-) - Sean Patrick Floyd
因此,getList中的get(index)操作速度更快,LinkedList中的get操作速度更慢,而LinkedList中的add(index,object)更快,ArrayList中的更慢,更正确吗? - Anjan Baradwaj
@SeanPatrickFloyd:是的,对不起,我再次阅读评论后得到了:P。 - MD Sayem Ahmed


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

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


1
2017-09-11 07:08





ArrayList 由数组支持 LinkedList 支持节点与refernece链接。

所以操作上 ArrayList 是在数组上的actaully evalute操作。添加操作以分摊的常量时间运行,即添加n个元素 O(n) 时间。所有其他操作都以线性时间运行(粗略地说)。恒定因子与低的因子相比较低 LinkedList 实现。

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

阅读更多文档 -


1
2017-09-11 07:05





链接列表将在添加每个元素时创建新节点,而不在数组列表中。

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


0
2017-09-11 07:07