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运行得更快。有人能解释一下哪一个在所用时间方面表现更好吗?另外,如果代码有问题,请告诉我。谢谢!
- 您是否查看了stackoverflow.com/questions/322715/&hellip;?此链接是相关问题中的第一个
- 对于一个100的循环,差异可以忽略不计。尝试一个1000万或更多的循环。
- stackoverflow.com/questions/322715/&hellip;和stackoverflow.com/questions/10656471/&hellip;的副本
- programcreek.com/2013/03/arraylist-vs-linkedlist-vs-vector javarevisited.blogspot.in/2012/02/&hellip;link可能会帮助您
- @瓦伊巴维德赛-成功了!我增加了要添加到列表中的元素的数量,现在我可以看到,在LinkedList中,在随机索引处插入比在ArrayList中插入更好。
如果您需要执行大量的插入操作,而不是频繁地进行查找,请使用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。
- "如果您必须执行大量的插入操作,而不是频繁地查找,请使用LinkedList"我想知道对于大列表末尾的插入操作,这是否正确。linkedList在插入之前几乎必须迭代整个过程,而arraylist可以依赖于system.arraycopy(),后者是本机操作,应该足够快。这里必须有一个神奇的元素门限,使arraylist更有效(至少在这个特定的场景中如此)
- @seanPatrickFloyd:如果使用double-pointer-strategy实现LinkedList的底层链表,这意味着如果它为链表的开始和结束都保留指针,那么就不必遍历整个结构。我见过有人用这种方式实现链表以实现高效插入,内存开销只是一个额外的指针。
- 这正是java.util.LinkedList所做的(刚刚检查了代码)。我接受纠正。或者更确切地说:现在在中间插入是极端情况:—)
- 那么,get(index)操作在arraylist中更快,在linkedlist中更慢,而add(index,object)在linkedlist中更快,在arraylist中更慢,对吗?
- @ AnjanBaradwaj:是这样,在AARYLIST上获得更快,但是对于LinkedList,EDCOX1的2代价在最坏的情况下与ARARYLIST相同,因为如果插入中间,它也可能需要移位项目。
- 作为结论,是否有任何具体的案例建议使用哪一个?
- @Anjanbaradwaj:如果你在LinkedList上使用add(object)(我是在谈论openjdk的实现,见我之前的评论中的链接),那么它将比ArrayList的add(object)更好。
- @Anjanbaradwaj:是的,简单的add(object)在LinkedList上更快,简单的get(index)在ArrayList上更快。使用LinkedList频繁插入,使用ArrayList频繁查找。
- @Sayem也许你误解了我,因为我实际上同意你的观点(我检查了Sun版本,它有一个双指针策略,这是它需要的,因为LinkedList实现了deque)。
- 实际上,这比那要微妙一点。首先,插入到EDOCX1[5]的末尾是在摊余的固定时间内进行的,因此"平均"(即,在许多插入中)它将具有与EDOCX1[0]相同的增长。最坏的情况是速度较慢,但如果你不在一个实时ESQ项目上工作(例如,一个必须在下一帧时间内完成的游戏),这可能就没有那么有趣了。另外,即使渐近增长更大,也必须考虑系数;memcpy非常快。即使在小列表等的非附加插入中,ArrayList也可能击败LinkedList。
- @是的,对不起,我是在再次阅读评论后得到的。
在读取方面,数组列表总是比链接列表快。arraylist基本上是数组实现,为数组分配的内存是按顺序分配的,因此读取速度更快。但是,当使用需要在列表之间插入或删除的列表时,链接列表会更快。因为它只需要在节点之间添加链接。在这两种情况下,数组列表将变慢。用法可以是:
arraylist-更快的读取操作、插入、删除列表之间的速度较慢。链表-读取操作比数组列表慢,但插入、删除列表之间的速度更快。
ArrayList由数组支持,LinkedList支持的节点与reference链接。
因此,对ArrayList的操作实际上是对数组的操作进行评估。加法运算是在摊余的固定时间内进行的,也就是说,添加n个元素需要O(n)时间。所有其他的操作都在线性时间内运行(大致来说)。与LinkedList的实现相比,常数因子较低。
在LinkedList上,所有的操作都按照双链表的预期执行。索引到列表中的操作将从开始或结束遍历列表,以更接近指定索引的为准。
阅读更多文档-
当添加每个元素时,LinkedList将涉及创建新节点,而它不在数组列表中。
如果知道初始大小,则在创建时将其传递给ArrayList,这样就避免了数组的重建。如new ArrayList(100);