ArrayDeque作为Queue内存占用更低、GC压力更小,因其底层为循环数组,无Node对象封装开销,元素紧凑连续存储;LinkedList每个元素需包装为含item/next/prev的Node对象,在64位JVM下单个Node实占40–64字节,10万Integer时内存达5–7MB,远超ArrayDeque的1.0–1.5MB。

ArrayDeque 作为 Queue 使用时,内存占用更低、GC 压力更小,核心原因在于它没有节点封装开销,元素以紧凑方式连续存储在数组中;而 LinkedList 每个元素都要包装成 Node 对象,带来显著的内存冗余和对象分配负担。
内存布局决定基础开销差异
ArrayDeque 底层是一个循环数组(Object[] elements),只维护两个 int 类型索引(head 和 tail),无额外字段。插入元素只是将引用写入数组指定位置,不创建新对象。
LinkedList 每个元素必须封装为 Node 实例,每个 Node 至少含三个字段:item、next、prev。在 64 位 JVM(未开启压缩指针)下:
- 对象头通常占 12 字节,对齐填充后常达 16 字节
- 三个引用字段各占 8 字节,共 24 字节
- 单个 Node 实际内存占用普遍在 40–64 字节之间(含 Integer 等包装类自身开销)
实测数据:10 万个 Integer 的对比
存入 10 万个 Integer 对象时:
立即学习“Java免费学习笔记(深入)”;
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
- ArrayDeque 占用堆内存约 1.0–1.5 MB(含初始容量 16 及扩容余量)
- LinkedList 占用堆内存约 5–7 MB(主要来自 10 万个 Node 对象)
差距主要来自 Node 的固定开销,而非元素本身——即使存的是 int[] 或 String,LinkedList 的节点膨胀效应依然存在。
GC 压力来源完全不同
ArrayDeque 在生命周期内极少创建临时对象:
- push/offer 操作仅更新数组引用和索引,无 new 行为
- 扩容仅发生在 tail 溢出时,且是批量复制(System.arraycopy 高度优化)
- 长期运行中对象数量稳定,GC 周期几乎不受影响
LinkedList 则在每次 offer 时都 new 一个 Node:
- 高频入队场景下,短时间内产生大量短命对象
- 这些 Node 很快被 poll 移除,进入年轻代 GC 范围,触发频繁 Minor GC
- 若队列深度波动大,还会加剧内存碎片和晋升压力
使用建议:何时该坚持用 ArrayDeque
只要满足以下条件,Queue 场景应默认选 ArrayDeque:
- 不需要在队列中间插入或删除(Queue 接口本身也不支持)
- 能接受 null 元素被禁止(push/offer null 直接抛 NPE,利于早期发现问题)
- 线程安全由上层控制(如单线程解析、BFS 遍历、方法内局部变量等)
若必须支持 null 或需线程安全,优先考虑 ConcurrentLinkedQueue 或 LinkedBlockingQueue,而不是退回到 LinkedList。

















