LinkedHashMap继承了HashMap,实现了Map接口。由此可以看出LinkedHashMap是一个HashMap,推理出其在HashMap的基础上增加了某些东西。
成员变量
/*** 双链接列表中的头(最年长的)。*/transient LinkedHashMap.Entry<K,V> head;/*** 双链接列表的尾部(最年轻的)。*/transient LinkedHashMap.Entry<K,V> tail;/*** 此链接哈希映射的迭代排序方法:<tt>true</tt>* 对于访问顺序,<tt>false</tt>对于插入顺序。*(即存键值对进去是什么顺序,迭代打印出来的就是什么顺序)。* @serial*/final boolean accessOrder;
构造方法

因为LinkedHashMap继承了HashMap,所以两者底层架构并没有很大的差异(同样都是数组+链表+红黑树)。
两者的差别就在:LinkedHashMap的数据节点多了2个指针:头指针head和尾指针tail
它有5个构造方法,比HashMap多了1个,其他的四个构造方法和HashMap的都差不多
LinkedHashMap(): 无参构造,调用父类HashMap的无参构造(初始容量为16,负载因子为0.75),并且设置accessOrder=false;(即使用插入顺序)
/*** 构造一个空的插入顺序<tt>LinkedHashMap</tt>实例* 默认初始容量(16)和负载系数(0.75)。*/public LinkedHashMap() {super();accessOrder = false;}
LinkedHashMap(int initialCapacity): 调用父类HashMap(initialCapacity),指定初始容量,并且设置accessOrder=false;(即使用插入顺序)
/*** 构造一个空的插入顺序<tt>LinkedHashMap</tt>实例* 具有指定的初始容量和默认负载系数(0.75)。*/public LinkedHashMap(int initialCapacity) {super(initialCapacity);accessOrder = false;}
LinkedHashMap(int initialCapacity, float loadFactor): 调用父类HashMap(initialCapacity, loadFactor),指定初始容量和负载因子,并且设置accessOrder=false;(即使用插入顺序)
/**** 构造具有指定初始容量和负载因子的空插入顺序LinkedHashMap实例。*/public LinkedHashMap(int initialCapacity, float loadFactor) {super(initialCapacity, loadFactor);accessOrder = false;}
LinkedHashMap(Map<? extends K, ? extends V> m): 调用父类HashMap的空参构造,并且设置accessOrder=false;(即使用插入顺序),调用putMapEntries()方法将map集合转为LinkedHashMap集合。容量由入参map集合决定
/*** 使用与指定映射相同的映射构造插入顺序的LinkedHashMap实例。* LinkedHashMap实例是使用默认负载因子(0.75)和初始容量创建的,* 初始容量足以在指定的映射中保存映射。** @param m the map whose mappings are to be placed in this map* @throws NullPointerException if the specified map is null*/public LinkedHashMap(Map<? extends K, ? extends V> m) {super();accessOrder = false;putMapEntries(m, false);}
LinkedHashMap(int initialCapacity,float loadFactor,boolean accessOrder): 调用父类HashMap的(initialCapacity, loadFactor),并且设置指定的accessOrder(即使用指定的顺序)。此三个入参的构造方法在HashMap并没有
/*** 使用指定的初始容量、* 负载因子和排序模式构造一个空的LinkedHashMap实例。** @param initialCapacity the initial capacity* @param loadFactor the load factor* @param accessOrder the ordering mode - <tt>true</tt> for* access-order, <tt>false</tt> for insertion-order* @throws IllegalArgumentException if the initial capacity is negative* or the load factor is nonpositive*/public LinkedHashMap(int initialCapacity,float loadFactor,boolean accessOrder) {super(initialCapacity, loadFactor);this.accessOrder = accessOrder;}
静态内部类
这是增加了head、tail两个指针的类型,继承了HashMap.Node
//普通LinkedHashMap条目的节点子类。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);}}
linkNodeLast()方法
// link at the end of listprivate void linkNodeLast(LinkedHashMap.Entry<K,V> p) {LinkedHashMap.Entry<K,V> last = tail;tail = p;if (last == null)head = p;else {p.before = last;last.after = p;}}
访问顺序
- HashMap插入的顺序与取出的顺序是不一样的,即HashMap是无序的
- LinkedHashMap插入的顺序与取出的顺序是一样的,即LinkedHashMap是有序的

开启accessOrder访问顺序(即accessOrder=true)
可以看到被访问后的元素,被置顶了。也就是说,LinedHashMap访问某元素,某元素将被置顶。这样的功能应用在LRU缓存方面。 经常访问的元素就可以很快速地找到了,而不被经常访问的元素可以沉到底甚至可以被覆盖,LinkedHahsMap这样的功能使得它在缓存技术方面发扬光大。
总结
从上面的访问顺序,也可以总结出,遍历LinkedHashMap是按照从链表开始扫描,扫到尾部的。
get元素后,元素被放到链表的尾部,所以每次get后再遍历LinkedHashMap,get的元素都会出现在末尾。
