LinkedHashMap 默认保持插入顺序,因其在哈希表基础上用双向链表记录插入轨迹;启用 accessOrder=true 后转为访问顺序,遍历顺序依赖迭代器,扩容不破坏顺序,但 clear 重插、accessOrder 模式或反射修改会破坏顺序。

LinkedHashMap 默认就保持插入顺序,不需要额外配置;但必须理解它靠双向链表 + 哈希表协同实现,不是“自动排序”而是“记录插入轨迹”。
为什么 LinkedHashMap 能记住插入顺序
普通 HashMap 只维护哈希桶和节点数组,节点散列后位置无序;LinkedHashMap 在每个 Node 上额外加了 before 和 after 引用,形成一条双向链表。每次 put() 新键值对,不仅写入哈希表,还把节点追加到链表尾部。
这意味着:只要不触发 accessOrder = true(见下一点),遍历 keySet()、entrySet() 或 values() 都严格按 put() 顺序返回。
accessOrder = true 会破坏插入顺序
构造 LinkedHashMap 时传入第三个参数 true,就会启用访问顺序模式——每次 get() 或 put() 已存在 key,对应节点会被移到链表尾部。此时遍历结果反映的是“最近访问顺序”,而非插入顺序。
立即学习“Java免费学习笔记(深入)”;
- 默认构造:
new LinkedHashMap()→accessOrder = false(安全) - 显式启用:
new LinkedHashMap(16, 0.75f, true)→ 插入顺序失效 - 常见误用:复制别人代码时没注意第三个参数,导致遍历时顺序“跳变”
遍历时顺序依赖迭代器,不是内部结构自动保证
LinkedHashMap 的有序性只在通过其自身迭代器访问时生效。一旦转成数组或流中间操作,顺序可能被打破:
Mapmap = new LinkedHashMap<>(); map.put("a", 1); map.put("b", 2); map.put("c", 3); // ✅ 安全:迭代器保障顺序 for (Map.Entry e : map.entrySet()) { System.out.println(e.getKey()); // a → b → c } // ⚠️ 风险:toArray() 不保证顺序(尽管当前 JDK 实现是,但规范未承诺) Object[] arr = map.keySet().toArray(); // 不推荐依赖此顺序 // ⚠️ 风险:parallelStream() 可能乱序(除非显式 sorted()) map.entrySet().parallelStream().forEach(System.out::println); // 顺序不确定
扩容或 rehash 不影响插入顺序
很多人担心 resize() 会打乱链表。实际上,LinkedHashMap 扩容时会**重建哈希桶,但保持原链表节点顺序逐个 rehash 并追加到新链表尾部**。所以即使容量从 16 扩到 32,entrySet() 遍历仍严格维持插入顺序。
唯一真正破坏顺序的操作只有:
- 手动调用
clear()后重新插入 - 使用
accessOrder = true后频繁get() - 用反射或 Unsafe 强行修改内部
head/tail指针(不建议)










