关于java:在List中间插入和删除时,LinkedList比ArrayList更快。 只是“在中间”?

LinkedList is faster than ArrayList when insertion and removal in the middle of the List. Just “in the middle”?

好吧,有很多关于LinkedList和ArrayList的讨论,但是当我在"Thinking in Java"中看到这个描述时,我仍然感到困惑:

LinkedList也实现了像ArrayList那样的基本List接口,但它
执行某些操作(在List中间插入和删除)更多
比ArrayList高效。

我不知道为什么它强调"在List的中间",我认为当插入List的开头时,ArrayList还需要传递后面的元素,而且它比LinkedList更快?


以前的答案非常好,但这些帮助我想象发生了什么,当我需要更详细的解释时:

删除

enter image description here

enter image description here

插入

enter image description here


重点是暗示这样一个事实,即ArrayList内部需要移动元素,并保持开放内存以进行进一步的插入,从而导致它移位和复制元素。 LinkedList将简单地创建一个节点,然后将前一节点的next节点设置为新节点,并将新节点的next节点设置为列表中的下一个节点。

还应该注意的是,虽然经典的LinkedList在中间的插入方面表现优异,但有时候ArrayList也会表现得好,或者比LinkedList更好(这在多种语言之间实际上很常见,包括C ++ [Bjarne Stroustrup]实际上有一个关于概念的讲座])。您应该仔细考虑您正在做什么,并使用基准来做出正确的决定。


ArrayList由数组支持,而LinkedList由2个引用支持(nextprevious,即由DoublyLinkedList支持)。 LinkedList更快,因为一旦调用add(int index,E element),它就不需要复制数组并将元素向右移动一个单元格。
ArrayList在插入中间(或索引0和currentSize之间的任何位置)时复制/移位元素,因此需要更多时间。而LinkedList只需更改2个指针/引用。

ArrayList.java:

1
2
3
4
5
6
7
public void add(int index, E element) {
..
// copying elements
System.arraycopy(elementData, index, elementData, index + 1,
             size - index);
..
}

LinkedList.java

1
2
3
4
5
6
7
8
9
10
11
12
13
public void add(int index, E element) {
    addBefore(element, (index==size ? header : entry(index)));
}

private Entry<E> addBefore(E e, Entry<E> entry) {
Entry<E> newEntry = new Entry<E>(e, entry, entry.previous);
// just changing the pointers
newEntry.previous.next = newEntry;
newEntry.next.previous = newEntry;
size++;
modCount++;
return newEntry;
}