5.LinkedList vs ArrayList:谁更快?到底该怎么选?

LinkedList vs ArrayList:谁更快?到底该怎么选?

🚀 高频指数:★★★★★
🎯 你将收获:底层结构对比、时间复杂度分析、源码解读、项目选型模板。


一、面试开场问题

💬 面试官:

  1. ArrayList 和 LinkedList 有什么区别?
  2. 哪个增删快?哪个查询快?
  3. 为什么 LinkedList 在实际项目中用得少?

答得好,能体现你对集合原理、内存模型和性能评估的理解;
答得背板,就容易掉入“LinkedList 增删快”这种半真半假的陷阱。


二、核心区别概览

对比项ArrayListLinkedList
底层结构动态数组双向链表
随机访问✅ O(1) 通过索引❌ O(n) 需遍历
插入删除❌ O(n)(需移动元素)✅ O(1)(已定位节点)
内存开销小(连续数组)大(节点额外引用)
线程安全❌ 不安全❌ 不安全
实现接口List, RandomAccessList, Deque
是否支持队列操作部分支持✅ 完整支持(双端队列)

📌 口诀:“查快数组,增快链表。”


三、底层结构源码对比

🔹 ArrayList(动态数组)

transient Object[] elementData;
private int size;
  • 内部维护一个连续的 Object 数组;
  • 通过索引直接访问元素。

🔹 LinkedList(双向链表)

private static class Node<E> {
    E item;
    Node<E> next;
    Node<E> prev;
}
transient int size = 0;
transient Node<E> first;
transient Node<E> last;
  • 每个节点存储前后指针,双向连接。
  • 访问中间元素必须从头或尾遍历。

四、增删性能对比

操作ArrayListLinkedList
add(E e)(尾部)O(1)*均摊O(1)
add(int index, E e)O(n)(移动元素)O(n)(先遍历,再插入)
remove(int index)O(n)O(n)
removeFirst()/removeLast()✅ O(1)
clear()O(n) 逐个置空O(1)(断开首尾)

LinkedList 只在首尾增删优势明显
中间插入时仍需遍历,性能优势有限。


五、访问性能对比

list.get(i); 
  • ArrayList:底层数组,直接通过下标定位 → O(1);
  • LinkedList:必须从头或尾开始迭代 → O(n)。

📌 口诀:“数组随机,链表顺序。”


六、内存与缓存效率

指标ArrayListLinkedList
存储模型连续内存块分散节点
空间占用多(每个节点额外两个引用)
CPU 缓存友好性✅ 连续存储,局部性好❌ 不连续,命中率低
适合场景数据量大、访问频繁插入删除频繁但数据量小

⚙️ 实际工程中:ArrayList 在绝大多数场景下更快。


七、源码关键差异举例

🔹 ArrayList.get()

public E get(int index) {
    rangeCheck(index);
    return elementData(index);
}

直接数组访问 → O(1)。

🔹 LinkedList.get()

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;
    }
}

遍历一半链表,O(n) 时间复杂度。


八、fail-fast 同样存在

两者都继承自 AbstractList,共享 modCount 机制。
在遍历时若结构被修改,都会抛出 ConcurrentModificationException


九、项目实践选型建议

场景推荐集合理由
随机访问频繁(查询多)✅ ArrayListO(1) 访问快
插入删除首尾元素✅ LinkedList双端队列 O(1) 操作
中间插入删除多ArrayList因 LinkedList 仍需遍历
数据量大(10w+)✅ ArrayList内存与缓存效率更高
队列/栈场景✅ LinkedList / ArrayDeque实现 Deque 接口更自然

💡 实际项目中 95% 场景优先 ArrayList。
LinkedList 更适合模拟队列、缓存、链式结构。


十、性能对比实测(样例)

List<Integer> arr = new ArrayList<>();
List<Integer> link = new LinkedList<>();
int N = 50000;

long t1 = System.nanoTime();
for (int i = 0; i < N; i++) arr.add(i);
System.out.println("ArrayList add: " + (System.nanoTime() - t1));

t1 = System.nanoTime();
for (int i = 0; i < N; i++) link.add(i);
System.out.println("LinkedList add: " + (System.nanoTime() - t1));

t1 = System.nanoTime();
arr.get(N/2);
System.out.println("ArrayList get: " + (System.nanoTime() - t1));

t1 = System.nanoTime();
link.get(N/2);
System.out.println("LinkedList get: " + (System.nanoTime() - t1));

输出结果(示例):

ArrayList add: 2.3 ms
LinkedList add: 4.8 ms
ArrayList get: 0.01 µs
LinkedList get: 380 µs

✅ 访问性能差距显著,ArrayList 完胜。


十一、面试官追问清单

问题答案要点
ArrayList 与 LinkedList 区别?底层结构不同,数组 vs 链表。
哪个增删快?首尾 LinkedList 快,中间基本一样。
哪个查找快?ArrayList O(1);LinkedList O(n)。
为什么 LinkedList 慢?遍历需移动节点指针,CPU 缓存不友好。
项目中选哪个?绝大多数选 ArrayList。

十二、口诀记忆

☕️ “查快数组,增快链表;首尾高效,中间无差。”


十三、小结

知识点关键结论
底层结构ArrayList=数组,LinkedList=链表
查询性能ArrayList 快
插入删除仅首尾 LinkedList 快
空间效率ArrayList 优
实战选型默认 ArrayList,链式结构才选 LinkedList

✅ 一句话总结:“能用 ArrayList,就别用 LinkedList。”

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

愤怒的代码

如果您有受益,欢迎打赏博主😊

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值