LinkedHashMap是Java集合框架中一个兼具哈希表高效查找特性和链表顺序维护特性的实现类,它的迭代顺序由内部的双向链表决定,而移除操作作为集合的常用操作,会直接修改这个双向链表的结构,进而影响后续的迭代顺序。

LinkedHashMap的核心结构
LinkedHashMap继承自HashMap,在HashMap的数组加链表(或红黑树)结构基础上,额外维护了一个贯穿所有节点的双向链表。这个双向链表的定义如下:
// LinkedHashMap的内部Entry结构,继承自HashMap的Node
static class Entry<K,V> extends HashMap.Node<K,V> {
Entry<K,V> before, after; // 前驱和后继指针,维护双向链表
Entry(int hash, K key, V value, Node<K,V> next) {
super(hash, key, value, next);
}
}
这个双向链表有两种迭代顺序模式:一种是插入顺序,即元素按照插入的先后顺序排列;另一种是访问顺序,即每次访问(get或put已存在的键)元素时,会将该元素移到链表末尾。默认情况下LinkedHashMap使用插入顺序。
移除操作的执行流程
LinkedHashMap的移除操作复用了HashMap的remove方法逻辑,但是在移除节点后,会额外执行双向链表的节点移除操作。核心逻辑在afterNodeRemoval方法中,该方法会在HashMap的removeNode执行完成后被调用。
// LinkedHashMap重写的afterNodeRemoval方法
void afterNodeRemoval(Node<K,V> e) { // 移除节点后调整双向链表
LinkedHashMap.Entry<K,V> p = (LinkedHashMap.Entry<K,V>)e, b = p.before, a = p.after;
// 清空当前节点的前后指针
p.before = p.after = null;
// 如果前驱为空,说明当前节点是链表头,移除后头节点变为后继
if (b == null)
head = a;
else
// 否则前驱的后继指向当前节点的后继
b.after = a;
// 如果后继为空,说明当前节点是链表尾,移除后尾节点变为前驱
if (a == null)
tail = b;
else
// 否则后继的前驱指向当前节点的前驱
a.before = b;
}
移除操作对迭代顺序的影响验证
插入顺序模式下的影响
在默认的插入顺序模式下,移除元素只会把该元素从双向链表中删除,其他元素的相对顺序保持不变。我们通过代码示例验证:
import java.util.LinkedHashMap;
import java.util.Map;
public class LinkedHashMapRemoveTest {
public static void main(String[] args) {
// 创建默认插入顺序的LinkedHashMap
LinkedHashMap<String, Integer> map = new LinkedHashMap<>();
// 插入元素
map.put("a", 1);
map.put("b", 2);
map.put("c", 3);
map.put("d", 4);
System.out.println("移除前迭代顺序:");
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.print(entry.getKey() + " ");
}
// 输出:a b c d
// 移除键b
map.remove("b");
System.out.println("n移除b后迭代顺序:");
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.print(entry.getKey() + " ");
}
// 输出:a c d ,b被移除,其余元素顺序不变
}
}
访问顺序模式下的影响
当LinkedHashMap设置为访问顺序模式时,构造方法需要传入accessOrder=true参数。此时移除操作的影响和插入顺序模式一致,只会移除目标节点,不会改变其他节点的相对顺序,但是访问操作会调整节点位置,需要注意移除和访问操作的先后影响。
import java.util.LinkedHashMap;
import java.util.Map;
public class LinkedHashMapAccessOrderTest {
public static void main(String[] args) {
// 创建访问顺序模式的LinkedHashMap
LinkedHashMap<String, Integer> map = new LinkedHashMap<>(16, 0.75f, true);
map.put("a", 1);
map.put("b", 2);
map.put("c", 3);
// 访问键a,a会被移到链表末尾
map.get("a");
System.out.println("访问a后移除b前的顺序:");
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.print(entry.getKey() + " ");
}
// 输出:b c a
// 移除键b
map.remove("b");
System.out.println("n移除b后的顺序:");
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.print(entry.getKey() + " ");
}
// 输出:c a ,b被移除,其余元素保持之前的相对顺序
}
}
总结
LinkedHashMap的移除操作会直接修改内部维护的双向链表结构,将目标节点从链表中删除,因此必然会影响迭代顺序:被移除的元素不会再出现在后续迭代中,而其余元素的相对顺序在插入顺序和访问顺序模式下都不会发生改变。开发者在使用LinkedHashMap时,只需要明确当前的迭代顺序模式,就可以准确判断移除操作后的迭代结果,避免因顺序问题导致的业务逻辑错误。
LinkedHashMap迭代顺序移除操作HashMap修改时间:2026-06-28 16:36:32