只有 LinkedHashMap(默认 accessOrder=false)保证迭代器按插入顺序返回元素;其通过维护双向链表实现,而 HashMap、TreeMap、EnumMap 等均不满足该条件。

要识别一个 Map 的迭代器是否始终按插入顺序返回元素,关键不是看“它叫什么”,而是看它的规范行为、底层机制和构造方式。Java 中只有 LinkedHashMap 在默认配置下明确保证这一点;其他常见 Map 实现(如 HashMap、TreeMap、EnumMap)都不满足该条件。
看类名与继承关系:必须是 LinkedHashMap
LinkedHashMap 是 HashMap 的子类,但它额外维护了一个双向链表。这个链表不参与哈希查找,只负责记录插入时的节点顺序。只要没启用访问顺序模式(即构造时未传入 accessOrder = true),它的 entrySet()、keySet() 和 values() 迭代器就一定从链表头开始、沿 after 指针逐个遍历——这天然对应插入顺序。
- 普通 HashMap:迭代顺序由哈希桶分布决定,无定义,不可预测
- TreeMap:按键自然序或自定义比较器排序,与插入无关
- EnumMap:按枚举常量声明顺序迭代,不是插入顺序
- ImmutableMap(Guava):若用
copyOf()或 builder 构建,可保持源顺序,但这是其 API 合约,非底层结构保障
查构造方式:确认 accessOrder = false(默认值)
LinkedHashMap 提供了带 accessOrder 参数的构造函数:
-
new LinkedHashMap()或new LinkedHashMap(16, 0.75f)→accessOrder = false,即插入顺序模式(默认) -
new LinkedHashMap(16, 0.75f, true)→ 访问顺序模式,get/put 都会把节点移到链表尾,此时迭代顺序反映的是最近访问次序,不是插入次序
只要没显式传 true,就安全。覆盖已有 key 的 put(k, v) 不会改变节点在链表中的位置,因此插入顺序依然稳定。
验行为表现:用最小可证伪操作验证
不依赖文档,直接写一段可复现的测试代码:
- 依次 put("a", 1), put("c", 3), put("b", 2)
- 遍历 entrySet(),检查输出是否严格为 a→c→b
- 再 put("a", 99),再次遍历 → 仍为 a→c→b(值更新,位置不变)
- 若结果是 a→b→c 或 c→a→b 等,则不是插入顺序保障型 Map
避坑提示:别被“有序”二字误导
有些 Map 声称“有序”,但含义不同:
- TreeMap 的“有序”指按键排序,和插入动作完全解耦
- EnumMap 的“有序”指按 enum 定义顺序,插入顺序无法控制
- C++ std::map 根本不保证插入顺序,它强制按键升序排列,迭代器遍历必然是排序后顺序
- 任何基于哈希但未额外维护链表的实现(如大多数第三方 Map),都不具备插入顺序能力
真正可靠、轻量、JDK 原生支持插入顺序遍历的,只有默认模式下的 LinkedHashMap。










