LinkedHashMap 源码解读:序言
2023-10-23 09:20:18
LinkedHashMap 源码剖析:优雅掌控键值对顺序
在 Java 集合框架中,当我们需要管理键值对的数据结构时,HashMap 是一个强大的选择。然而,HashMap 存在一个局限性:它无法保证元素的插入或访问顺序。对于需要保持键值对顺序的场景,LinkedHashMap 应运而生。本文将深入剖析 LinkedHashMap 的源码,探究其是如何优雅地掌控键值对顺序的。
探秘 LinkedHashMap
LinkedHashMap 继承自 HashMap,因此它具备 HashMap 的基本特性,如基于哈希表实现、允许 null 键和值等。然而,LinkedHashMap 的独特之处在于它维护了一个双向链表,将键值对按照插入顺序连接起来。
双向链表的奥秘
LinkedHashMap 中的双向链表被称为 Entry。每个 Entry 都包含三个引用:
- key:键
- value:值
- next/prev:指向下一个/前一个 Entry 的引用
通过维护这个双向链表,LinkedHashMap 可以轻松地保持元素的插入顺序。当一个新的键值对添加到 LinkedHashMap 中时,它会被附加到双向链表的末尾。当访问元素时,LinkedHashMap 可以通过双向链表高效地找到它。
优雅地处理扩容
与 HashMap 类似,LinkedHashMap 也需要处理扩容。当 LinkedHashMap 达到其容量限制时,它会创建一张新的哈希表,并将元素重新哈希到新表中。
有趣的是,LinkedHashMap 在扩容时也维护着双向链表的顺序。它通过在新的哈希表中为每个链表创建一个头结点来实现这一点。然后,它遍历双向链表,将每个元素添加到头结点后面,从而保留了元素的顺序。
EntrySet 和 Iterator
LinkedHashMap 提供了 EntrySet 和 Iterator,允许我们遍历它的键值对。EntrySet 是一个 Set,包含 LinkedHashMap 中的所有 Entry。Iterator 是一个迭代器,可以顺序地访问 EntrySet 中的元素。
范例代码
// 创建一个 LinkedHashMap
LinkedHashMap<String, Integer> map = new LinkedHashMap<>();
// 添加键值对
map.put("One", 1);
map.put("Two", 2);
map.put("Three", 3);
// 遍历 LinkedHashMap
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + " : " + entry.getValue());
}
输出结果:
One : 1
Two : 2
Three : 3
正如我们所见,键值对按插入顺序打印,这正是 LinkedHashMap 的魅力所在。
结论
LinkedHashMap 通过维护一个双向链表,为 Java 集合框架提供了对键值对顺序的优雅控制。它在处理扩容时保持顺序的能力进一步突显了其强大的功能。掌握 LinkedHashMap 的运作机制对于希望在其应用程序中管理有序数据的 Java 开发者至关重要。