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 对象时:
- ArrayDeque 占用堆内存约 1.0–1.5 MB(含初始容量 16 及扩容余量)
- LinkedList 占用堆内存约 5–7 MB(主要来自 10 万个 Node 对象)
差距主要来自 Node 的固定开销,而非元素本身——即使存的是 int[] 或 String,LinkedList 的节点膨胀效应依然存在。
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
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。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










