面试官经常问的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)


相关推荐
thinktik13 分钟前
AWS EKS 实现底层EC2计算资源的自动扩缩[AWS 中国宁夏区]
后端·aws
uhakadotcom21 分钟前
什么是OpenTelemetry?
后端·面试·github
知其然亦知其所以然29 分钟前
MySQL 社招必考题:如何优化特定类型的查询语句?
后端·mysql·面试
用户40993225021234 分钟前
给接口加新字段又不搞崩老客户端?FastAPI的多版本API靠哪三招实现?
后端·ai编程·trae
RoyLin34 分钟前
TypeScript设计模式:代理模式
前端·后端·typescript
用户6120414922131 小时前
C语言做的文本词频数量统计功能
c语言·后端·敏捷开发
IT_陈寒2 小时前
Vue3性能优化实战:这5个技巧让我的应用加载速度提升了70%
前端·人工智能·后端
在逃牛马3 小时前
【Uni-App+SSM 宠物项目实战】Day16:订单提交
后端
高松燈3 小时前
浮点数类型导致金额计算错误复盘总结
后端