LinkedHashMap 默认保持插入顺序,无需额外配置;其底层采用哈希表+双向链表实现,仅当显式传入true参数时才启用访问顺序模式。

LinkedHashMap 默认就保持插入顺序,不需要额外配置
Java 的 LinkedHashMap 在设计上就明确区分了 HashMap 和 TreeMap:它底层用哈希表 + 双向链表实现,只要不启用访问顺序模式,插入顺序天然保留。很多人误以为要调用某个方法或传参才能“开启”顺序,其实根本不用。
- 默认构造函数
new LinkedHashMap()就是插入顺序 - 带初始容量和负载因子的构造函数(如
new LinkedHashMap(16, 0.75f))也维持插入顺序 - 只有显式传入
true作为第三个参数时,才会切换成访问顺序:new LinkedHashMap(16, 0.75f, true)
为什么遍历 LinkedHashMap 有时看起来“乱序”?
常见错觉来源不是 LinkedHashMap 失效,而是代码中混用了其他集合类型或误操作:
- 把
LinkedHashMap赋值给Map接口变量后,再用entrySet().iterator()遍历——这本身没问题,但若后续被强转成HashMap或重新初始化,顺序就丢了 - 在多线程环境下未加同步,导致插入过程被干扰(
LinkedHashMap不是线程安全的) - 使用了
putAll()从一个无序 Map(如HashMap)导入数据,此时顺序由源 Map 决定,而非LinkedHashMap自身
遍历时如何确保拿到插入顺序?
最稳妥的方式是直接遍历 keySet()、values() 或 entrySet(),三者都严格按插入顺序返回:
LinkedHashMapmap = new LinkedHashMap<>(); map.put("first", 1); map.put("second", 2); map.put("third", 3); // 以下三种方式都输出 first → second → third for (String key : map.keySet()) { System.out.println(key); } for (Integer value : map.values()) { System.out.println(value); } for (Map.Entry entry : map.entrySet()) { System.out.println(entry.getKey() + "=" + entry.getValue()); }
- 避免用
map.keySet().toArray()后再排序或打乱——数组本身不保存顺序语义 - 如果需要反向遍历,不能依赖
Collections.reverse()作用于 keySet,而应手动用ArrayList包装后倒序 - 注意
forEach()方法(JDK 8+)也遵循插入顺序,和 for-each 一致
和 TreeMap 的顺序行为有本质区别
TreeMap 按键的自然顺序或比较器排序,跟插入无关;而 LinkedHashMap 的顺序只取决于插入动作本身,哪怕键是乱序字符串、重复插入同一 key 也会更新值但不改变位置。
立即学习“Java免费学习笔记(深入)”;
- 重复
put("a", 1)后再put("a", 99),键"a"在链表中的位置不变,只是对应 value 被覆盖 - 如果需要“最近插入优先”的淘汰策略(比如 LRU 缓存),才需启用访问顺序:
new LinkedHashMap(16, 0.75f, true),此时每次get()都会把该 entry 移到链表尾 - 访问顺序模式下,
put()和get()都会触发布局调整,性能略低于插入顺序模式
LinkedHashMap 实例、没在中间换成别的 Map、也没开访问顺序,插入顺序就稳稳的。最容易被忽略的是往里塞数据前,源数据本身是否有序——比如从 JSON 解析来的 Map 如果底层是 HashMap,那放进 LinkedHashMap 也救不回原始顺序。










