一.LinkedHashMap的概述
LinkedHashMap是通过哈希表和链表来实现的,它通过维护一个链表来保证对哈希表迭代时的有序性,而这个有序性是指键值对插入的顺序性。另外,当哈希表中重复插入某个键的时候,并不会影响到原来的有序性,也就是说,假设你插入的键的顺序为 1、2、3、4,后来再次插入 2,迭代时的顺序还是 1、2、3、4,而不会因为后来插入的 2 变成 1、3、4、2。(但其实我们可以改变它的规则,使它变成 1、3、4、2)
LinkedHashMap的实现主要分为两部分,一部分是哈希表,另外一部分是链表。哈希表部分继承了HashMap,拥有了HashMap那一套搞笑的操作,所以我们要看的就是LinkedHashMap中链表的部分,理解它是如何来维护有序性的。
LinkedHashMap的大致实现如下图所示,当然链表和哈希表中相同的键值对都是指向同一个对象,这里把他们分来来画是为了呈现出比较清晰的结构
二,属性
在看属性之前,我们先来看一下LinkedHashMap的申明
public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V>{}
从上面申明中我们可以看见LinkedHashMap是继承自HashMap的,所以它已经从HashMap那里继承了与哈希表相关的操作了,那么在LinkedHashMap中,它可以专注于链表实现的部分,所以与链表实现相关的属性如下
LinkedhashMap的链表节点继承了HashMap的节点,而且每个节点都包含了前指针和后指针,所以这里可以看出它是一个双向链表
static class Entry<K,V> extends HashMap.Node<K,V> {Entry before, after;
Entry(
int hash, K key, V value, Node<K,V> next) {
super(hash, key, value, next);{
}{
}
//头指针
transient LinkedHashMap.Entry<K,V> head;
//尾指针
transient LinkedHashMap.Entry<K,V> tail;
//默认为 false。当为 true 时,表示链表中键值对的顺序与每个键的插入顺
序一致,也就是说重复插入键,也会更新顺序
//简单来说,为 false 时,就是上面所指的 1、2、3、4 的情况;为 true 时,
就是 1、3、4、2 的情况
final boolean accessOrder;
三,方法
如果你有仔细看过 HashMap 源码的话,你会发现 HashMap 中有如下三个方法:
// Callbacks to allow LinkedHashMap post-actions
void afterNodeAccess(Node p) { }
void afterNodeInsertion(boolean evict) { }
void afterNodeRemoval(Node<K,V> p) { }
如果你没有注意到注释的解释的话,你可能会很奇怪为啥会有三个空方法呢,并且有不少的地方还调用他们,其实这三个方法表示的是在访问,插入,删除某个节点之后,进行一些处理,他们在LinkedhashMap中各有实现。LinkedhashMap正是通过这三个方法来保证联保的插入,删除的有序性