linkedhashset通过内部linkedhashmap实现插入顺序维护,其元素作为key存入map,value为哑值present;linkedhashmap.entry继承hashmap.node并添加before/after指针构成双向链表,插入时同步更新哈希桶和链表尾部,迭代时从head沿after遍历,保证插入序。

LinkedHashSet 本身不直接维护双向链表,而是通过内部的 LinkedHashMap 实现插入顺序的保持。 它底层完全复用 LinkedHashMap 的结构和逻辑,而 LinkedHashMap 的 Entry 类型(如 LinkedHashMap.Entry)正是一个继承自 HashMap.Node 并额外包含 before 和 after 引用的双向链表节点。
LinkedHashSet 的底层是 LinkedHashMap
LinkedHashSet 的所有操作(add、remove、iterator)都委托给其内部持有的一个 LinkedHashMap 实例。这个 map 的 key 就是 LinkedHashSet 中的元素,value 统一使用一个静态的哑值 PRESENT(即 new Object())。因此:
- 每次调用
add(e),实际执行的是map.put(e, PRESENT) - LinkedHashMap 在 put 过程中,不仅完成哈希桶中的单向链表/红黑树插入,还会把新节点追加到双向链表末尾(
accessOrder=false时) - 这个双向链表的头尾由 LinkedHashMap 的
head和tail字段维护
LinkedHashMap.Entry 是真正的双向链表节点
不同于 HashMap 中的 Node(只有 next),LinkedHashMap 的内部节点类定义类似:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
static class Entry<k> extends HashMap.Node<k> {
Entry<k> before, after; // 指向前驱和后继节点
Entry(int hash, K key, V value, Node<k> next) {
super(hash, key, value, next);
}
}</k></k></k></k>
每当一个新元素被加入 LinkedHashMap(即 LinkedHashSet.add),该 Entry 实例会被:
- 插入到哈希桶的单向链表中(用于快速查找)
- 同时通过
linkNodeLast(this)方法接入双向链表尾部,更新tail.after = this、this.before = tail、tail = this
迭代时按双向链表顺序遍历
LinkedHashSet.iterator() 返回的迭代器,本质上是 LinkedHashMap 的 LinkedKeyIterator,它从 head 开始,沿着 after 引用逐个访问节点,直到 after == null:
- 第一次
next()返回head.key - 后续依次返回
head.after.key、head.after.after.key…… - 这个顺序严格等于元素插入的先后顺序(非访问顺序)
注意:不是“每个 LinkedHashSet 自己存一份链表”
双向链表属于 LinkedHashMap 实例的成员(transient LinkedHashMap.Entry<k> head</k> / tail),LinkedHashSet 只是一个薄包装。所以:
- 多个 LinkedHashSet 实例之间互不影响各自的链表
- 链表节点(Entry)同时参与哈希索引和顺序链接,空间上是一份数据两套指针
- 删除元素时,除了从哈希桶中移除,也会从双向链表中解链(更新 before.after 和 after.before)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










