linkedhashmap 比 hashmap 多占内存是设计使然,因其节点额外增加 before 和 after 引用字段维护双向链表,每条目多约 16 字节,百万条目约增 15 mb(+15%);accessorder=true 不增加内存但改变访问行为,适合 lru 缓存等需顺序语义场景。

LinkedHashMap 比 HashMap 多占内存,不是 bug,是设计使然——它用额外空间换来了顺序保障。
为什么多出的内存用于维护双向链表
HashMap 的底层是数组 + 链表/红黑树,每个 Node 只存 hash、key、value、next 四个字段;而 LinkedHashMap 的节点类是 LinkedHashMap.Entry,继承自 HashMap.Node,并额外增加了 before 和 after 两个引用字段,用来串起所有条目的双向链表。
- 每条数据多出 16 字节(64 位 JVM 下,两个对象引用各占 8 字节)
- 100 万个条目 ≈ 多消耗 15 MB 左右(实测约 +15% 总内存)
- 链表本身不依赖哈希桶数量,只与实际元素个数线性相关
accessOrder=true 时内存开销不变,但行为不同
构造时传入 true(如 new LinkedHashMap(16, 0.75f, true))不会增加额外字段,before/after 始终存在;变化的是 get() 和 put() 的逻辑:每次访问都会触发节点移动到链表尾部。这意味着:
- 内存占用和插入顺序模式完全一致
- 但迭代时头部永远是最久未访问的条目,适合 LRU 缓存淘汰
- 频繁
get()会带来微小的链表指针更新开销,非零但通常可忽略
别误判“多占内存”等于“不能用”
实际项目中是否值得用 LinkedHashMap,取决于你是否需要顺序语义:
- 做缓存且需自动淘汰最久未用项?
accessOrder=true+removeEldestEntry是标准解法 - 记录操作日志、导出配置、调试时按插入顺序观察?不用 LinkedHashMap 就得自己维护 List + Map,反而更费内存和代码
- 纯高频随机查、写,且顺序无关?那确实该选
HashMap - 注意:JVM 对小对象的内存对齐可能让单条
Entry实际占用比理论值略高,但比例关系稳定
真正容易被忽略的是:这个“多出来的内存”不是静态开销,而是随数据量线性增长的;如果你的 Map 常驻百万级条目,就得把这 15% 纳入容量规划——而不是等 OOM 才发现是 LinkedHashMap 在悄悄吃掉堆内存。










