Java 当插入和删除列表中间时,LIKEDLIST比ARARYLIST快。只是;在中间;?

Java 当插入和删除列表中间时,LIKEDLIST比ARARYLIST快。只是;在中间;?,java,arraylist,linked-list,Java,Arraylist,Linked List,好吧,关于LinkedList和ArrayList有很多讨论,但是当我在《用Java思考》中看到这个描述时,我仍然感到困惑: LinkedList也像ArrayList一样实现基本列表接口,但是 执行某些操作(插入和删除列表中间< /强>) 比ArrayList更有效 我不知道它为什么强调“在列表中间”,我认为当插入到列表的开头时,ArrayList也需要转移后面的元素,并且它比Link KistList更快?< P> >代码> ARRAYLIST/COD>由一个数组支持,而链接列表由2个引用支

好吧,关于LinkedList和ArrayList有很多讨论,但是当我在《用Java思考》中看到这个描述时,我仍然感到困惑:

LinkedList也像ArrayList一样实现基本列表接口,但是 执行某些操作(<强>插入和删除列表中间< /强>) 比ArrayList更有效


我不知道它为什么强调“在列表中间”,我认为当插入到列表的开头时,ArrayList也需要转移后面的元素,并且它比Link KistList更快?

< P> >代码> ARRAYLIST/COD>由一个数组支持,而<代码>链接列表由2个引用支持。(
next
previous
即,由
DoublyLinkedList
支持)。
LinkedList
更快,因为调用add(int index,e element)后,它不需要复制数组并将元素向右移动一个单元格。 <代码> AlayList当插入中间(或在索引0和CurrnStand之间的任何地方)复制/移位元素,因此,需要更多的时间,而 > LIKEDLIST/<代码>只需要改变2个指针/引用。 ArrayList.java:

public void add(int index, E element) {
..
// copying elements
System.arraycopy(elementData, index, elementData, index + 1,
             size - index);
..
}
LinkedList.java

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;
}
public void add(int索引,E元素){
addBefore(元素,(索引==大小?标题:条目(索引));
}
专用条目addBefore(E,条目){
Entry newEntry=新条目(e,Entry,Entry.previous);
//只是换个指针而已
newEntry.previous.next=newEntry;
newEntry.next.previous=newEntry;
大小++;
modCount++;
返回新条目;
}

数组列表
由数组支持,而
链接列表
由两个引用支持(
下一个
上一个
即,由
双链接列表
支持).
LinkedList
更快,因为调用add(int-index,E-element)后,它不需要复制数组并将元素向右移动一个单元格。 <代码> AlayList当插入中间(或在索引0和CurrnStand之间的任何地方)复制/移位元素,因此,需要更多的时间,而 > LIKEDLIST/<代码>只需要改变2个指针/引用。 ArrayList.java:

public void add(int index, E element) {
..
// copying elements
System.arraycopy(elementData, index, elementData, index + 1,
             size - index);
..
}
LinkedList.java

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;
}
public void add(int索引,E元素){
addBefore(元素,(索引==大小?标题:条目(索引));
}
专用条目addBefore(E,条目){
Entry newEntry=新条目(e,Entry,Entry.previous);
//只是换个指针而已
newEntry.previous.next=newEntry;
newEntry.next.previous=newEntry;
大小++;
modCount++;
返回新条目;
}

重点是提示这样一个事实,即ArrayList在内部需要移动元素,并为进一步插入保持开放内存,从而导致其移动和复制元素。LinkedList只需创建一个节点,然后将上一个节点的
下一个
节点设置为新节点,并将将新节点添加到列表中的下一个节点


还应注意,虽然经典的Link KeListListin在中间插入时会很好,但是经常有一个ARARYLIST也会执行,或者比Link KekDista更好(这实际上是在一个以上语言之间的通用,包括C++(Bjarne Stroustrup实际上有一个关于概念的讲座))。你应该仔细考虑你正在做什么,并使用基准来做出正确的决定。

强调的是,在内部,ARAYLIST将需要转换元素,并保持打开的内存,以便进一步插入,使其移位和复制元素。链接列表将简单地创建一个节点,然后设置<代码>将上一个节点的节点设置为新节点,并将新节点的节点设置为列表中的下一个节点


还应注意,虽然经典的Link KeListListin在中间插入时会很好,但是经常有一个ARARYLIST也会执行,或者比Link KekDista更好(这实际上是在一个以上语言之间的通用,包括C++(Bjarne Stroustrup实际上有一个关于概念的讲座))。你应该仔细考虑你在做什么,用基准来做出正确的决定。

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

删除

插入


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

删除

插入


有些情况下,LinkedList是更好的选择。十年后我需要它一次。一般来说,如果你的列表经常更新,使用它是有意义的。在其他情况下,没有性能提升,但总是会受到内存损失。所以坚持使用ArrayList,你会很好。有些情况下,LinkedList是e更好的选择。十年后我需要它一次。一般来说,如果你的列表经常更新,使用它是有意义的。在任何其他情况下,没有性能提升,但总是会受到内存损失。所以坚持使用ArrayList,你会很好。