关于Java:哪一个运行得更快,ArrayList 还是LinkedList?

Which one runs faster, ArrayList or LinkedList?

本问题已经有最佳答案,请猛点这里访问。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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运行得更快。有人能解释一下哪一个在所用时间方面表现更好吗?另外,如果代码有问题,请告诉我。谢谢!


如果您需要执行大量的插入操作,而不是频繁地进行查找,请使用LinkedList。如果执行的查找多于插入,请使用ArrayList

原因如下:ArrayList由具有初始容量的数组支持。因此,如果您不断地向列表中插入项目,在某一点上,它必须重新调整其数组容量以适应新插入的项目,并且如果您执行索引特殊插入,它可能还必须移动现有项目。另一方面,LinkedList由一个链表支持,在链表中,创建一个项目总是在一个固定的时间内执行—创建一个项目并将其分配到列表的末尾。此处不进行重新调整。

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

从上面的讨论中可以看出,当你有更多的插入要做时,LinkedList总是优于ArrayList,因为后者有一个与插入相关的内部调整成本,而前者没有。另一方面,如果你有不经常的插入和频繁的查找,ArrayList总是优于LinkedList。因为对于后者,您可能需要遍历整个链接列表结构来找到所需的项,而前者将能够在恒定时间内通过数组索引快速找到您的项。

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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


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

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


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

因此,对ArrayList的操作实际上是对数组的操作进行评估。加法运算是在摊余的固定时间内进行的,也就是说,添加n个元素需要O(n)时间。所有其他的操作都在线性时间内运行(大致来说)。与LinkedList的实现相比,常数因子较低。

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

阅读更多文档-

  • 数组列表
  • 链表

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

如果知道初始大小,则在创建时将其传递给ArrayList,这样就避免了数组的重建。如new ArrayList(100)