文章目录
一、结构不同
LinkedList:它基于双向链表。每个元素(我们叫它节点)不仅存储数据,还存储了指向前后元素的两个指针。
ArrayList:它基于动态数组。这意味着它需要一段连续的内存来存储数据📦,而不是像LinkedList那样通过指针相互连接。每个元素都通过索引快速访问
如下图所示:
二、访问速度
LinkedList:因为数据是通过链表存储的,要访问某个特定位置的元素,你需要从头(或尾)开始,逐个走过每个节点才能找到目标。这个过程就像翻找一个很长的链子,一环一环地往下走,所以速度会很慢。
源码:
public E get(int index) {
checkElementIndex(index);
return node(index).item;
}
Node<E> node(int index) {
if (index < (size >> 1)) {
Node<E> x = first;
//循环遍历链表找到对应的节点
for (int i = 0; i < index; i++){
x = x.next;
return x;
} else {
Node<E> x = last;
for (int i = size - 1; i > index; i--){
x = x.prev;
return x;
}
}
}
ArrayList:因为数组是连续存储的,所有元素的内存地址是连续的。所以,你可以直接通过索引来快速访问某个元素,就像一份清单,上面标明每个商品在超市里的具体位置。
源码:
public E get(int index) {
rangeCheck(index);
return elementData(index);
}
//直接反回对应数组下表数据
E elementData(int index) {
return (E) elementData[index];
}
三、插入和删除操作的不同
LinkedList:因为它是链表结构,插入和删除操作非常方便,特别是在头部或尾部插入和删除元素的时候。你只需要调整前后节点的指针指向,几乎不会影响其他节点。然而在中间位置进行操作,你还得从头开始找这个位置(通过for循环找到下标,浪费时间)。
ArrayList:在末尾插入是比较快的,因为只需要将新元素放在最后一个位置。但是如果你想在中间插入或删除元素,所有后面的元素都要往前或往后移位,浪费时间。
1、决定效率有两个因素:数据量和位置。
- 数据量较小时,没有明显区别
- 数据量较大时,大约在数据量的十分之一时,LinkedList就没有明显优势
- 后半段插入时,LinkedList效率明显低于ArrayList,数据量越大越明显
2、普遍说法是“LinkedList添加删除快”,这里是有前提条件的
- 往集合中间插入数据时ArrayList比linkedList慢
- ArrayList正好扩容的时候添加数据要比LinkedList慢
四、内存占用情况
LinkedList:由于每个节点除了存储数据外,还要存储指向前后节点的两个指针🧷,所以相比ArrayList,它占用的内存更多。
ArrayList:它只需要存储数据本身,没有额外的指针开销。虽然在增长时可能需要重新分配内存空间,但通常内存占用相对较少。
五、使用场景
LinkedList:适用于需要频繁插入和删除元素的场景,尤其是在队列的头部和尾部操作时⏩。比如:当你需要模拟一列排队系统时👥,LinkedList非常合适。
ArrayList:适用于快速访问数据的场景,尤其是频繁通过索引来读取数据的情况📑。如果你经常要遍历和访问元素,比如展示商品列表🛒,ArrayList会表现得更好。