前面几篇博客Java容器之Hashtable源码分析、Java容器之HashMap源码分析分别分析了HashMap
、Hashtable
的源码,此篇博客我们分析一下LinkedHashMap
容器,看看它又有什么花样。
注明:以下源码分析都是基于jdk 1.8.0_221
LinkedHashMap源码分析目录
一、LinkedHashMap
容器概述(一图以蔽之)
LinkedHashMap
类的申明如下:
public class LinkedHashMap<K,V>
extends HashMap<K,V>
implements Map<K,V>
可以看出LinkedHashMap
是HashMap
子类(建议先看看HashMap
再来看捏 → Java容器之HashMap源码分析),大胆推测一下,LinkedHashMap
底层用HashMap
存储节点,只是展示给你的是一个Linked
状态。
1、LinkedHashMap
容器的自我定位
看过博主前面HashMap
、Hashtable
源码分析或者了解一点Map
结构的小伙伴,肯定知道HashMap
的定位是单线程处理(读、写高效),Hashtable
的定位是支持并发读写(引入锁机制,降低效率),那么这个LinkedHashMap
的定位又是什么呢?先来看个例子:
public class Main {
public static void main(String[] args) {
// 新建一个linkedHashMap
LinkedHashMap<String, String> linkedHashMap = new LinkedHashMap<>();
// 依次插入三个key-value
linkedHashMap.put("老王", "我是谁");
linkedHashMap.put("老赵", "我在哪");
linkedHashMap.put("老李", "我要干嘛");
// 遍历输出linkedHashMap中的key-value
for (Map.Entry<String, String> entry : linkedHashMap.entrySet()) {
System.out.println(entry.getKey() + "\t" + entry.getValue());
}
}
}
可以看出LinkedHashMap
能按照插入的顺序给你输出,即一种Linked
的状态,其实这就是它的最主要特点。
2、LinkedHashMap
容器数据结构图
LinkedHashMap
容器比较简单,所有的key-value
节点都是存在HashMap
容器中(前面说过LinkedHashMap
继承HashMap
),只是加上before
、after
指针。一句话概括就是 LinkedHashMap
= HashMap
+ 双链表。
注明:在JDK1.8中,HashMap
的hash桶
实现引入了红黑树(参考Java容器之HashMap源码分析),但是我们此处主要是讨论LinkedHashMap
的Linked
属性,为了方便画图,所以结构示意图没有画出来。
二、LinkedHashMap
类的属性与内部类
1、Entry
内部类
在HashMap
存储key-value
的类为Node
(属性主要包括hash
、key
、value
),在LinkedHashMap
类用于要记录Linked
状态,所以增加一个继承Node
的内部类Entry
。Entry
类只是增加before
、after
指针而已,在LinkedHashMap
用Entry
对象存key-value
。
/**
* 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);
}
}
2、LinkedHashMap
新增属性
LinkedHashMap
类中新增三个主要的属性,head
、tail
分别指向外部展示的list
头部、尾部,accessOrder
属性的作用是list中节点顺序是否随get
方法调用而改变。
/**
* Linked list 头部
*/
transient LinkedHashMap.Entry<K,V> head;
/**
* Linked list 尾部
*/
transient LinkedHashMap.Entry<K,V> tail;
/**
* = true,每次调用get方法都会将查找到的key-value放入尾部
*/
final boolean accessOrder;
备注
:这里的accessOrder
有人翻为访问顺序
,其实根本不用翻译这个词。因为它容器与插入顺序
搞混,从而搞乱LinkedHashMap
有序到底什么有序。你只要记住LinkedHashMap
是key-value
插入顺序有序,accessOrder
变量的作用是调用get方法是否会将查找到的节点放入尾部即可!
三、LinkedHashMap
类构造器
LinkedHashMap
类一共有5个构造器,涉及initialCapacity
、loadFactor
、accessOrder
三个参数的初始化。
/**
* @param initialCapacity 初始容量(hashMap.table数组长度)
* @param loadFactor 负载因子(hashMap中的参数,
* initialCapacity * loadFactor就是HashMap容器可存放的key-value阈值,这里不再重复介绍了)
*/
public LinkedHashMap(int initialCapacity, float loadFactor) {
// super关键字,调用父类HashMap的响应构造器
super(initialCapacity, loadFactor);
// 默认维护的list不随get方法调用改变
accessOrder = false;
}
/**
* @param initialCapacity 初始容量(hashMap.table数组长度)
*/
public