跳转到主内容
新派编程网 - 新潮编程理念,全新技术课堂!

在Java中LinkedList与ArrayList如何取舍_Java列表结构对比解析

绝大多数日常场景下应优先使用ArrayList,因其CPU缓存友好、随机访问快、内存占用小且JVM优化充分;仅在需高频头尾增删且完全不访问中间索引时才考虑LinkedList。 什么时候该用
ArrayList
而不是
LinkedList
绝大多数日常场景下,
ArrayList
是更优选择。它底层是动态数组,CPU缓存友好、随机访问快、内存占用小,且现代JVM对数组做了大量优化。 常见适用场景包括: 频繁按索引读取元素(
get(i)
),比如遍历、查找、分页 批量添加末尾元素(
add(e)
),扩容摊还成本低(
O(1)
) 需要与数组互转(
toArray()
/
Arrays.asList()
) 使用
Stream
或第三方库(如 Apache Commons Collections),它们内部多针对数组结构优化 注意:
ArrayList
在中间插入/删除(
add(i, e)
/
remove(i)
)仍是
O(n)
,但实际性能往往比
LinkedList
的指针操作更快——因为避免了对象分配、GC压力和缓存不命中。 哪些情况真有必要选
LinkedList
LinkedList
唯一不可替代的用途是:需要在**头尾高频增删**,且**完全不访问中间索引**。 立即学习 “ Java免费学习笔记(深入) ”; 典型例子: 实现栈(
push/pop
→
addFirst()/removeFirst()
) 实现队列(
offer/poll
→
addLast()/removeFirst()
) 作为双端队列(
Deque
)参与线程安全的生产者-消费者逻辑(但此时应优先考虑
ConcurrentLinkedQueue
) 不要因为它“链表”就默认支持快速插入——
LinkedList.get(i)
是
O(n)
遍历,比
ArrayList
慢一个数量级。实测在 10k 元素时,随机访问慢 5–10 倍。 Eclipse导入Android或其他的JAVA项目的正确方法 WORD版 本文档主要讲述的是Eclipse导入Android或其他的JAVA项目的正确方法;希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看 下载
add(index, element)
在两者中的行为差异 表面签名一致,底层代价天差地别:
ArrayList.add(i, e)
:先将索引
i
及之后所有元素右移一位(数组拷贝),再插入;最坏
O(n)
,但全是连续内存复制,CPU效率高
LinkedList.add(i, e)
:先从头或尾遍历到第
i
个节点(取决于
i
靠近哪端),再修改前后指针;平均
O(n/2)
,且每次遍历都是非连续内存访问,容易触发缓存失效 尤其当
i
接近中间位置时,
LinkedList
不仅没优势,反而更慢。JDK 源码里甚至为
LinkedList
的
get(i)
做了方向优化(从 head 或 tail 走更短路径),但这无法抵消硬件层面的劣势。 内存开销与 GC 影响常被低估
LinkedList
每个元素额外持有两个引用(
prev
和
next
),加上对象头、对齐填充,单个节点通常占 24–32 字节 ;而
ArrayList
的元素直接存入数组,无额外引用开销。 例如存 10 万个
Integer
:
ArrayList: ~100_000 × 4B (int) + 数组头 ≈ 400KB LinkedList: ~100_000 × (24–32B) ≈ 2.4–3.2MB
更大的问题是:
LinkedList
创建大量短期存活的小对象(每个节点),加剧 Young GC 频率。在吞吐敏感或内存受限服务中,这点可能成为瓶颈。 真实项目中,除非明确压测证明
LinkedList
在特定操作上胜出,否则默认用
ArrayList
;若需高效头尾操作,优先查
ArrayDeque
——它用循环数组实现,兼具
ArrayList
的内存效率和
LinkedList
的头尾操作性能。

相关文章