linkedhashmap 通过双向链表维护插入顺序,每个节点含 before/after 引用,插入时追加至尾部;其迭代器沿链表遍历,故按插入序返回元素;hashmap 无此链表,节点仅按 hash 分布,无法保证顺序。

LinkedHashMap 用双向链表记住你放进去的顺序,不是靠哈希表本身,而是额外加了一条链——把每次新插入的节点串起来,头尾相接,形成一条“插入时间线”。
为什么 HashMap 不行,而 LinkedHashMap 可以?
HashMap 的底层是数组 + 单向链表/红黑树,节点只按 hash 分布,彼此之间没有顺序关联。插入先后完全不影响存储位置,自然无法保证顺序。
LinkedHashMap 在 HashMap 基础上,让每个 Entry(内部类 Node)多持有两个引用:before 和 after,指向它在插入链表中的前一个和后一个节点。所有新节点都追加到链表尾部,头结点固定,尾结点动态更新。
插入时链表怎么更新?
- 第一次插入:新建节点,head 和 tail 都指向它
- 后续插入:新节点的 before 指向当前 tail,当前 tail 的 after 指向新节点,再把 tail 更新为新节点
- 如果发生 key 重复(覆盖),默认不改变链表顺序;但可通过构造函数参数 accessOrder = false(默认)来保持插入序
遍历为啥就按插入顺序?
LinkedHashMap 重写了 keySet()、values()、entrySet() 的迭代器,它们不走哈希桶数组,而是从 head 开始,顺着 after 引用一路往后跳,直到 null。这就天然得到插入顺序,和哈希分布无关。
注意:remove 或 put 同 key 会怎样?
- remove(key):节点从哈希桶中摘除,同时从双向链表中断开(前后节点互相连接),链表长度减一
- put(key, value) 且 key 已存在:值被替换,但节点在链表中的位置不动(除非启用了访问顺序模式)
- 想实现 LRU 缓存?把 accessOrder 设为 true,get/put 都会把对应节点移到链表尾,再配合重写 removeEldestEntry() 就行










