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

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

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


四、 LinkedList的使用场景

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

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


相关推荐
金銀銅鐵5 小时前
[Java] 用 GUI 展示 EnumSet 增减元素时的内部变化(上)
java·后端·ai编程
念何架构之路6 小时前
go-grpc设计思想
开发语言·后端·golang
system_error_x6 小时前
SpringBoot 集成 Thymeleaf 简洁入门
java·spring boot·后端
步行cgn8 小时前
Spring MVC 视图机制的核心接口与类
java·开发语言·后端·spring·mvc
码事漫谈9 小时前
AI 读你的提示词,其实很没耐心
后端
用户8356290780519 小时前
如何使用 Python 格式化 Excel 单元格中的长文本
后端·python
我命由我123459 小时前
Python 开发 - Python 的 pathlib
java·开发语言·后端·python·学习·java-ee·学习方法
IT_陈寒10 小时前
Java性能优化完全指南
前端·人工智能·后端
电子IT笔记10 小时前
对接群晖NAS,上传和删除踩坑记录
前端·后端
Mk5987810 小时前
P4:把 Agent 的记忆搬进 Redis —— AgentScope-Java 工程化实战
后端