linkedhashmap通过双向链表维护插入或访问顺序:默认插入顺序,构造时传true启用访问顺序(lru),节点含before/after引用,扩容、删除、序列化均保持顺序,多线程需同步。

LinkedHashMap 通过维护一个双向链表来保证插入顺序或访问顺序。这个链表独立于哈希表的数组+链表/红黑树结构,专门记录元素的逻辑顺序。
插入顺序(默认行为)
每次调用 put() 或 putAll() 添加新键值对时,新节点不仅插入到哈希桶中,还会被追加到双向链表的尾部。已有 key 的更新(如重复 key 调用 put)不会改变链表位置,只更新 value 和哈希桶中的节点内容。
- 构造时使用默认构造方法
new LinkedHashMap()即启用插入顺序 - 链表头是第一个插入的元素,尾是最近插入的元素
- 迭代器(
keySet()、values()、entrySet())按链表顺序遍历,所以顺序稳定可预测
访问顺序(LRU 缓存模式)
只需在构造时传入 true 作为第三个参数:new LinkedHashMap(initialCapacity, loadFactor, true)。此时每次 get()、put()(含更新)、replace() 等访问操作,都会把对应节点移到链表尾部。
- 链表尾代表“最近访问”,头代表“最久未访问”
- 配合重写
removeEldestEntry()方法,可轻松实现固定大小的 LRU 缓存 - 注意:
get()触发移动仅在访问顺序模式下生效;插入顺序模式下 get 不改变链表
底层链表与哈希表协同工作
LinkedHashMap 的每个节点(LinkedHashMap.Entry)继承自 HashMap.Node,额外增加了 before 和 after 引用,用于维护双向链表。哈希表负责 O(1) 查找,链表负责顺序维护,两者互不干扰又紧密协作。
- 扩容时,链表顺序会整体迁移,保持原有相对顺序
- 删除节点时,同时从哈希桶和链表中移除,避免内存泄漏或顺序错乱
- 序列化时链表结构也被保存,反序列化后顺序依然保留
实际使用注意点
顺序保障依赖于标准的 Map 操作方式。手动修改内部字段、反射破坏链表、或混用非安全并发操作(如多线程未同步写入),都可能导致顺序异常或链表断裂。
- 多线程环境下,即使 LinkedHashMap 本身线程不安全,也要避免并发修改;可用
Collections.synchronizedMap(new LinkedHashMap())或改用ConcurrentHashMap+ 显式排序逻辑 - 不要重写
hashCode()或equals()导致哈希行为异常,否则可能影响插入/查找,间接破坏顺序感知 - 遍历时优先用增强 for 循环或迭代器,避免依赖 keySet().toArray() 等可能打乱顺序的操作
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











