面试官经常问的ArrayList 和 LinkedList的区别

面试官又双叒问这个问题了?ArrayList 和 LinkedList的区别是什么?经常再用但是有时候就是答不上来。 这个时候回答的时候肯定回答的不全面,随便糊弄一下。 那么到底有啥区别,我们今天好好分析一下


一、 底层结构:

怎么看他们的底层结构呢,你随便创建一个java文件,然后在里面创建一个ArrayList 和LinkedList然后点击就可以看到底层了,就像这样:

ArrayList: 上面这串英文翻译出来大概就是告诉我们它的底层是一个数组

LinkedList:

前一个节点,下一个节点,这就是一个链表结构的


二、 性能方面,我们测试那种极限的情况

场景1:随机访问

java 复制代码
// 初始化10万数据
List<Integer> arrayList = new ArrayList<>(1000000); 
List<Integer> linkedList = new LinkedList<>();
for (int i = 0; i < 1000000; i++) {
    arrayList.add(i);
    linkedList.add(i);
}

// 测试:访问第500000个元素
long start = System.nanoTime();
arrayList.get(500000); 
long arrayTime = System.nanoTime() - start;

start = System.nanoTime();
linkedList.get(500000); 
long linkedTime = System.nanoTime() - start;

System.out.println("ArrayList 耗时:" + arrayTime + " 纳秒");  
System.out.println("LinkedList 耗时:" + linkedTime + " 纳秒"); 

实测结果 :ArrayList 比 LinkedList 的查询速度快很多


场景2:头部疯狂插入数据

java 复制代码
// 测试:在头部插入10000次
// 初始化10万数据
List<Integer> arrayList = new ArrayList<>(1000000);
List<Integer> linkedList = new LinkedList<>();
for (int i = 0; i < 1000000; i++) {
    arrayList.add(i);
    linkedList.add(i);
}


long start =0 ;

start = System.nanoTime();
for (int i = 0; i < 10000; i++) {
    arrayList.add(0, i);
}
System.out.println("ArrayList 头部插入耗时:" + (System.nanoTime() - start));

start = System.nanoTime();
for (int i = 0; i < 10000; i++) {
    ((LinkedList<Integer>) linkedList).addFirst(i);
}
System.out.println("LinkedList 头部插入耗时:" + (System.nanoTime() - start));

实测结果LinkedList速度快很多,ArrayList 的数组迁移代价太高。


场景3:中部删除

java 复制代码
// 初始化10万数据
List<Integer> arrayList = new ArrayList<>(1000000);
List<Integer> linkedList = new LinkedList<>();
for (int i = 0; i < 1000000; i++) {
    arrayList.add(i);
    linkedList.add(i);
}


// 测试:删除中间1000个元素 (从索引50000开始)
long start = System.nanoTime();
start = System.nanoTime();
for (int i = 0; i < 1000; i++) {
    arrayList.remove(50000);
}
System.out.println("ArrayList 中部删除耗时:" + (System.nanoTime() - start));

start = System.nanoTime();
ListIterator<Integer> it = linkedList.listIterator(50000);
for (int i = 0; i < 1000; i++) {
    it.next();
    it.remove();
}
System.out.println("LinkedList 中部删除耗时:" + (System.nanoTime() - start));

关键发现

  1. LinkedList 删除并不总是快! 找到删除位置 (O(n)) + 删除 (O(1)) = 整体仍是 O(n)
  2. Iterator 是救星!ListIterator 定位后批量删除,避免重复遍历,效率反超 ArrayList

三、 内存情况

  • ArrayList

  • 基础消耗小 :数组本身很轻量 优化TIPnew ArrayList<>(10000) 预分配大小,避免反复扩容

  • LinkedList每个元素都是节点 :除了数据,还要存前后指针 内存碎片警告! 节点分散在内存各处,对CPU缓存不友好


四、 LinkedList的使用场景

  1. 需要快速合并集合
    linkedList.addAll(anotherList) 直接拼接链表,无需复制元素

  2. 中间位置极高频插入/删除
    前提:已通过Iterator定位好位置! 后续操作才是O(1)


相关推荐
6***830510 分钟前
SpringBoot教程(三十二) SpringBoot集成Skywalking链路跟踪
spring boot·后端·skywalking
有追求的开发者34 分钟前
2025 年终总结:一个 Python DevOps 的成长之路
后端
有追求的开发者38 分钟前
别再等缓存自己"热"起来了!Python后端必会的预热技巧 🚀
后端
乌暮39 分钟前
JavaEE初阶---《JUC 并发编程完全指南:组件用法、原理剖析与面试应答》
java·开发语言·后端·学习·面试·java-ee
内存不泄露40 分钟前
基于Django和Vue3的文件分享平台设计与实现
后端·python·django
有追求的开发者40 分钟前
别再搞混了!127.0.0.1 和 localhost 背后的秘密
后端
野生技术架构师42 分钟前
Spring Boot 4.0 预览版深度解析
java·spring boot·后端
PXM的算法星球1 小时前
用 semaphore 限制 Go 项目单机并发数的一次流量控制优化实践
开发语言·后端·golang
武子康1 小时前
大数据-210 如何在Scikit-Learn中实现逻辑回归及正则化详解(L1与L2)
大数据·后端·机器学习
Coder_Boy_1 小时前
Spring Boot 事务回滚异常 UnexpectedRollbackException 详解(常见问题集合)
java·spring boot·后端