简体   繁体   English

添加元素时java链表比arraylist慢?

[英]java linkedlist slower than arraylist when adding elements?

i thought linkedlists were supposed to be faster than an arraylist when adding elements? 我认为链接列表在添加元素时应该比arraylist更快? i just did a test of how long it takes to add, sort, and search for elements (arraylist vs linkedlist vs hashset). 我刚刚测试了添加,排序和搜索元素所需的时间(arraylist vs linkedlist vs hashset)。 i was just using the java.util classes for arraylist and linkedlist...using both of the add(object) methods available to each class. 我只是使用java.util类进行arraylist和linkedlist ...使用每个类可用的add(object)方法。

arraylist out performed linkedlist in filling the list...and in a linear search of the list. arraylist out在填写列表时执行链表...并在列表的线性搜索中执行。

is this right? 这是正确的吗? did i do something wrong in the implementation maybe? 我在实施中做错了吗?

** * ** * ** * ** * *** EDIT * ** * ** * ** * ** * ** * * ** * ** * ** * ** * *** 编辑 * ** * ** * ** * ** * ** * *

i just want to make sure i'm using these things right. 我只是想确保我正确使用这些东西。 here's what i'm doing: 这就是我正在做的事情:

public class LinkedListTest {

    private List<String> Names;

    public LinkedListTest(){
            Names = new LinkedList<String>();
    }

Then I just using linkedlist methods ie "Names.add(strings)". 然后我只使用链表列表方法,即“Names.add(strings)”。 And when I tested arraylists, it's nearly identical: 当我测试arraylists时,它几乎相同:

public class ArrayListTest {

    private List<String> Names;

    public ArrayListTest(){
            Names = new ArrayList<String>();
    }

Am I doing it right? 我做得对吗?

Yes, that's right. 恩,那就对了。 LinkedList will have to do a memory allocation on each insertion, while ArrayList is permitted to do fewer of them, giving it amortized O(1) insertion . LinkedList必须在每次插入时进行内存分配,而允许ArrayList执行更少的内存分配,从而使其分摊O(1)插入 Memory allocation looks cheap, but may be actually be very expensive. 内存分配看起来很便宜,但实际上可能非常昂贵。

The linear search time is likely slower in LinkedList due to locality of reference: the ArrayList elements are closer together, so there are fewer cache misses . 由于引用的局部性, LinkedList的线性搜索时间可能较慢: ArrayList元素更靠近,因此缓存未命中次数较少。

When you plan to insert only at the end of a List , ArrayList is the implementation of choice. 当您计划仅在List的末尾插入时, ArrayList是选择的实现。

Remember that: 请记住:

  • there's a difference in "raw" performance for a given number of elements, and in how different structures scale ; 对于给定数量的元素,以及不同结构如何扩展“原始”性能存在差异;
  • different structures perform differently at different operations, and that's essentially part of what you need to take into account in choosing which structure to use. 不同的结构在不同的操作中表现不同,这基本上是在选择使用哪种结构时需要考虑的部分。

So, for example, a linked list has more to do in adding to the end, because it has an additional object to allocate and initialise per item added, but whatever that "intrinsic" cost per item, both structures will have O(1) performance for adding to the end of the list, ie have an effectively "constant" time per addition whatever the size of the list, but that constant will be different between ArrayList vs LinkedList and likely to be greater for the latter. 因此,例如,链接列表在添加到结尾时还有更多工作要做,因为它有一个额外的对象来分配和初始化每个项目添加,但无论每个项目的“内在”成本如何,两个结构都将具有O(1)添加到列表末尾的性能,即无论列表的大小如何,每次添加都有一个有效的“常量”时间,但是该列表与ArrayList之间的常量会有所不同,后者可能会更大。

On the other hand, a linked list has constant time for adding to the beginning of the list, whereas in the case of an ArrayList, the elements must be "shuftied" along, an operation that takes some time proportional to the number of elements. 另一方面,链表有恒定的时间用于添加到列表的开头,而在ArrayList的情况下,元素必须“shuftied”,这是一个需要花费一些时间与元素数量成比例的操作。 But, for a given list size, say, 100 elements, it may still be quicker to "shufty" 100 elements than it is to allocate and initialise a single placeholder object of the linked list (but by the time you get to, say, a thousand or a million objects or whatever the threshold is, it won't be). 但是,对于给定的列表大小,比如100个元素,“shufty”100个元素可能比分配和初始化链表的单个占位符对象更快(但是当你到达时,比如,一千或一百万个物体或任何阈值,它不会是)。

So in your testing, you probably want to consider both the "raw" time of the operations at a given size and how these operations scale as the list size grows. 因此,在您的测试中,您可能希望同时考虑给定大小的操作的“原始”时间以及这些操作随着列表大小的增长而扩展

When adding an element to the back of a LinkedList (in Java LinkedList is actually a doubly linked list) it is an O(1) operation as is adding an element to the front of it. 将一个元素添加到LinkedList的后面时(在Java LinkedList中实际上是一个双向链表),它是一个O(1)操作,就像在它前面添加一个元素一样。 Adding an element on the i th position is roughly an O(i) operation. 在第i个位置添加元素大致是O(i)操作。

So, if you were adding to the front of the list, a LinkedList would be significantly faster. 因此,如果您要添加到列表的前面,则LinkedList会明显更快。

Why did you think LinkedList would be faster? 为什么你认为LinkedList会更快? In the general case, an insert into an array list is simply a case of updating the pointer for a single array cell (with O(1) random access). 在一般情况下,插入数组列表只是更新单个数组单元的指针(使用O(1)随机访问)的情况。 The LinkedList insert is also random access, but must allocate an "cell" object to hold the entry, and update a pair of pointers, as well as ultimately setting the reference to the object being inserted. LinkedList插入也是随机访问,但必须分配一个“单元”对象来保存条目,并更新一对指针, 以及最终设置对正在插入的对象的引用。

Of course, periodically the ArrayList's backing array may need to be resized (which won't be the case if it was chosen with a large enough initial capacity), but since the array grows exponentially the amortized cost will be low, and is bounded by O(lg n) complexity. 当然,可能需要定期调整ArrayList的后备阵列(如果选择具有足够大的初始容量,则不会出现这种情况),但由于阵列呈指数级增长,因此摊销成本将会很低,并且受到限制O(lg n)复杂性。

Simply put - inserts into array lists are much simpler and therefore much faster overall. 简单地说 - 插入数组列表要简单得多,因此总体来说要快得多。

Linked list may be slower than array list in these cases for a few reasons. 在这些情况下,链接列表可能比数组列表慢,原因有几个。 If you are inserting into the end of the list, it is likely that the array list has this space already allocated. 如果要插入列表的末尾,则阵列列表可能已经分配了此空间。 The underlying array is usually increased in large chunks, because this is a very time-consuming process. 底层数组通常以大块的形式增加,因为这是一个非常耗时的过程。 So, in most cases, to add an element in the back requires only sticking in a reference, whereas the linked list needs the creation of a node. 因此,在大多数情况下,在后面添加元素只需要粘贴在引用中,而链表需要创建节点。 Adding in the front and the middle should give different performance in for both types of list. 在前面和中间添加应该为两种类型的列表提供不同的性能。

Linear traversal of the list will always be faster in an array based list because it must only traverse the array normally. 在基于数组的列表中,列表的线性遍历总是更快,因为它必须只能正常遍历数组。 This requires one dereferencing operation per cell. 这需要每个单元一次解除引用操作。 In the linked list, the nodes of the list must also be dereferenced, taking double the amount of time. 在链表中,列表中的节点也必须被解除引用,占用的时间加倍。

ArrayList is faster in accessing random index data, but slower when inserting elements in the middle of the list, because using linked list you just have to change reference values. ArrayList访问随机索引数据的速度更快,但在列表中间插入元素时速度较慢,因为使用链表只需更改参考值。 But in an array list you have to copy all elements after the inserted index, one index behind. 但是在数组列表中,您必须在插入的索引后复制所有元素,后面有一个索引。

EDIT: Is not there a linkedlist implementation which keeps the last element in mind? 编辑:是不是有一个链表实现保持最后一个元素? Doing it this way would speed up inserting at the end using linked list. 这样做会加快使用链表的插入速度。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM