ArrayList还是LinkedList?性能可差千倍

本文详细分析了ArrayList和LinkedList在新增元素、删除元素以及遍历元素时的性能差异,指出ArrayList在头部添加元素时较慢,但在中间和尾部添加时效率优于LinkedList,而LinkedList在删除中间位置元素时效率较低。
摘要由CSDN通过智能技术生成

注意 for 循环中的 linkLast() 方法,它可以把链表重新链接起来,这样就恢复了链表序列化之前的顺序。很妙,对吧?

和 ArrayList 相比,LinkedList 没有实现 RandomAccess 接口,这是因为 LinkedList 存储数据的内存地址是不连续的,所以不支持随机访问。

03、ArrayList 和 LinkedList 新增元素时究竟谁快?

====================================

前面我们已经从多个维度了解了 ArrayList 和 LinkedList 的实现原理和各自的特点。那接下来,我们就来聊聊 ArrayList 和 LinkedList 在新增元素时究竟谁快?

1)ArrayList

ArrayList 新增元素有两种情况,一种是直接将元素添加到数组末尾,一种是将元素插入到指定位置。

添加到数组末尾的源码:

public boolean add(E e) {

modCount++;

add(e, elementData, size);

return true;

}

private void add(E e, Object[] elementData, int s) {

if (s == elementData.length)

elementData = grow();

elementData[s] = e;

size = s + 1;

}

很简单,先判断是否需要扩容,然后直接通过索引将元素添加到末尾。

插入到指定位置的源码:

public void add(int index, E element) {

rangeCheckForAdd(index);

modCount++;

final int s;

Object[] elementData;

if ((s = size) == (elementData = this.elementData).length)

elementData = grow();

System.arraycopy(elementData, index,

elementData, index + 1,

s - index);

elementData[index] = element;

size = s + 1;

}

先检查插入的位置是否在合理的范围之内,然后判断是否需要扩容,再把该位置以后的元素复制到新添加元素的位置之后,最后通过索引将元素添加到指定的位置。这种情况是非常伤的,性能会比较差。

2)LinkedList

LinkedList 新增元素也有两种情况,一种是直接将元素添加到队尾,一种是将元素插入到指定位置。

添加到队尾的源码:

public boolean add(E e) {

linkLast(e);

return true;

}

void linkLast(E e) {

final LinkedList.Node l = last;

final LinkedList.Node newNode = new LinkedList.Node<>(l, e, null);

last = newNode;

if (l == null)

first = newNode;

else

l.next = newNode;

size++;

modCount++;

}

先将队尾的节点 last 存放到临时变量 l 中(不是说不建议使用 I 作为变量名吗?Java 的作者们明知故犯啊),然后生成新的 Node 节点,并赋给 last,如果 l 为 null,说明是第一次添加,所以 first 为新的节点;否则将新的节点赋给之前 last 的 next。

插入到指定位置的源码:

public void add(int index, E element) {

checkPositionIndex(index);

if (index == size)

linkLast(element);

else

linkBefore(element, node(index));

}

LinkedList.Node node(int index) {

// assert isElementIndex(index);

if (index < (size >> 1)) {

LinkedList.Node x = first;

for (int i = 0; i < index; i++)

x = x.next;

return x;

} else {

LinkedList.Node x = last;

for (int i = size - 1; i > index; i–)

x = x.prev;

return x;

}

}

void linkBefore(E e, LinkedList.Node succ) {

// assert succ != null;

final LinkedList.Node pred = succ.prev;

final LinkedList.Node newNode = new LinkedList.Node<>(pred, e, succ);

succ.prev = newNode;

if (pred == null)

first = newNode;

else

pred.next = newNode;

size++;

modCount++;

}

先检查插入的位置是否在合

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值