linkedlist 比 arraylist 多出的内存开销主要来自每个 node 对象的额外指针字段(prev/next 各 4 或 8 字节)和对象头(约 12 字节),导致单个元素存储成本显著增加,空链表也需占用约 24 字节以上。

LinkedList 比 ArrayList 多出的内存开销,主要来自每个元素额外携带的指针字段,而非“整个链表结构”的统一开销。
每个节点多存两个引用(8 或 16 字节)
LinkedList 的底层是双向链表,每个元素封装在一个 Node 对象里。这个 Node 包含三个字段:
- item:存储实际数据(引用类型为 4/8 字节,取决于 JVM 是否开启指针压缩)
- next:指向后继节点的引用(通常 4 或 8 字节)
- prev:指向前驱节点的引用(同样 4 或 8 字节)
以 64 位 JVM + 开启指针压缩(默认)为例,每个 Node 额外比 ArrayList 中单个数组元素多占用约 8 字节(两个引用)。若存的是 Integer,ArrayList 数组中一个位置只存一个 4 字节的引用;而 LinkedList 中一个 Integer 就要包裹进一个至少 24 字节的对象(对象头 12 字节 + item 4 字节 + next 4 字节 + prev 4 字节,再加可能的填充对齐)。
没有连续数组带来的空间局部性,但不直接增加“字节数”
ArrayList 使用一块连续内存,JVM 可能紧凑分配;LinkedList 的 Node 分散在堆上,每个 Node 单独 new 出来,会带来:
- 更多对象头开销(每个 Node 都有独立对象头)
- 更易产生内存碎片,间接影响 GC 效率和实际内存利用率
- 缓存不友好——CPU 缓存预取失效,虽不增加静态内存计数,但运行时“有效内存成本”更高
不存数据时也有基础开销
空的 ArrayList 默认容量为 0 或 10(取决于构造方式),初始可能只占一个数组引用(4/8 字节)+ 对象头;而空的 LinkedList 必须持有 header Node(即 dummy 节点),它本身就是一个完整 Node 对象,哪怕 size == 0,也已占用约 24 字节以上。
扩容机制不导致“突发”内存增长,但累积更碎
ArrayList 在 add 时可能触发数组扩容(如 1.5 倍),造成短暂双倍内存占用;LinkedList 每次 add 都新建一个 Node,开销稳定但分散。长期看,LinkedList 总内存 = Σ(Node 对象大小),ArrayList ≈ 数组长度 × 元素引用大小 + 数组对象自身开销。当元素数量大时,LinkedList 的总内存通常明显更高——实测常高出 30%~50%。










