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


相关推荐
深入云栈17 分钟前
Netty 4.2.x 源码深度解析 (二十三):ByteBuf 核心设计 —— 索引、类型与零拷贝
java·后端·架构
JackJiang18 分钟前
IM踩坑:聊天消息ID怎么设计?一个UUID搞不定,我用双ID解决
后端·架构
开心猴爷20 分钟前
iOS 上架 App 流程
后端·ios
code_Bo1 小时前
不只命令行:我把跨 Agent 会话同步做成了桌面应用
前端·javascript·后端
用户8356290780511 小时前
使用 Python 控制 Excel 工作表的分页位置
后端·python
用户8356290780512 小时前
Python 如何在 Word 中添加和管理文档变量
后端·python
量化分析码农3 小时前
股票历史数据的复权参数对照:多级别返回的字段与数值差异
java·javascript·后端
程序员cxuan4 小时前
讲真,智能路由这事儿,还得看基元律动
人工智能·后端·程序员
vaskilab4 小时前
Schema 全绿,Agent 却把参数编造了
后端
Java与AI落地4 小时前
Spring AI 上手:给现有 Java 服务加一个能用的 AI 接口
后端