版本:jdk1.8
继承了HashMap
通过双向链表将所有节点连接起来
主要是实现了HashMap中留的几个空方法来完成自己的特性
数据可以按插入、读取的顺序访问
利用它的特性可以实现LRU(最近最少使用算法)
非线程安全
LinkedHashMap相关的UML
数组+链表/红黑树实现 红黑树这里我就没画,因为链表比较好展示
先来看看有哪些重要的属性 HashMap中的这里就不说了哈,大家可以自己去看看
双向链表中节点的数据结构
继承了HashMap中的Node,增加了前后指针
重要构造
来看看LinkedHashMap重要的几个方法
linkedHashMap.put
点进去发现调用的是是父类HashMap.put,实现了父类HashMap中的空方法afterNodeAccess、afterNodeInsertion
我们再来看看重写的newNode方法
通过newNode方法是在双端队列的尾部插入节点,在没有相同key的情况,用newNode方法先将节点插入到双端队列的尾部
/**
* 覆盖父类HashMap中的newNode
* 创建一个新的链表节点
* 并把p链接到双向链表的尾部
*/
Node<K,V> newNode(int hash, K key, V value, Node<K,V> e) {
LinkedHashMap.Entry<K,V> p =
new LinkedHashMap.Entry<K,V>(hash, key, value, e);
linkNodeLast(p);
return p;
}
/**
* 把p链接到双向链表的尾部
*/
private void linkNodeLast(LinkedHashMap.Entry<K,V> p) {
LinkedHashMap.Entry<K,V> last = tail;
tail = p;
if (last == null)//tail->head->null
head = p;//tail->head->p
else {//tail->p
p.before = last;
last.after = p;
}
}
更新节点:afterNodeAccess方法
如果按访问顺序,e之前不是在双端队列的队尾,就在它移至队尾
插入新的节点:afterNodeInsertion方法
如果是按访问顺序的话,且要removeEldestEntry方法返回的是true,则会删除双端队列的头结点(最近最少使用)
linkedHashMap.get
afterNodeAccess这里我就不重复说了,前面有说到过
linkedHashMap.remove
点进去发现调用的是是父类HashMap.remove,实现了父类HashMap中的空方法afterNodeRemoval
删除的节点:afterNodeInsertion方法
/**
* 覆盖HashMap afterNodeRemoval
* HashMap删除数据之后的回调
* 在双向链表中也移除掉对应的节点
*/
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;//便于gc
if (b == null)
head = a;//head->e.after
else
b.after = a;//b.after->e.before
if (a == null)
tail = b;//tail->e.after
else
a.before = b;//a.before->p.before
}
这里只是贴出了一些比较重要的方法,想要查看更完整的LinkedHashMap源码解析点击这里