介绍
LinkedHashMap是HashMap的子类
- Key和Value都允许空
 - 有序
 - key可重复可覆盖,value可重复
 - 非线程安全
 - 可用于实现LRU
 
public class LinkedHashMap<K,V>
    extends HashMap<K,V>
    implements Map<K,V>
 

LinkedHashMap的原理图:
LinkedHashMap是HashMap和双向链表的合二为一,即一个将所有Entry节点链入一个双向链表的HashMap(LinkedHashMap = HashMap + 双向链表)
LinkedHashMap 在不对HashMap做任何改变的基础上,给HashMap的任意两个节点间加了两条连线before指针和after指针,使这些节点形成一个双向链表。在LinkedHashMapMap中,所有put进来的Entry都保存在HashMap中,但由于它又额外定义了一个以head为头结点的空的双向链表,因此对于每次put进来Entry还会将其插入到双向链表的尾部。

LinkedHashMap和HashMap的Entry结构图:

常量&变量
    //序列化版本号
    private static final long serialVersionUID = 3801124242820219131L;
    /**
     * The head (eldest) of the doubly linked list.
     * 头节点,最老的元素
     */
    transient LinkedHashMap.Entry<K,V> head;
    /**
     * The tail (youngest) of the doubly linked list.
     * 尾节点,最新的元素
     */
    transient LinkedHashMap.Entry<K,V> tail;
    /**
     * The iteration ordering method for this linked hash map: <tt>true</tt>
     * for access-order, <tt>false</tt> for insertion-order.
     * 默认是false,则迭代时输出的顺序是插入节点的顺序。
     * 若为true,则输出的顺序是按照访问节点的顺序。为true时,可以在这基础之上构建LRU
     *
     * @serial
     */
    final boolean accessOrder;
 
- header是LinkedHashMap所维护的双向链表的头结点
 - tail是尾节点
 - accessOrder用于决定具体的迭代顺序
 
构造方法
详情查看hashmap源码
/**
     * Constructs an empty insertion-ordered <tt>LinkedHashMap</tt> instance
     * with the specified initial capacity and load factor.
     *
     * @param  initialCapacity the initial capacity
     * @param  loadFactor      the load factor
     * @throws IllegalArgumentException if the initial capacity is negative
     *         or the load factor is nonpositive
     */
    public LinkedHashMap(int initialCapacity, float loadFactor) {
        super(initialCapacity, loadFactor);
        accessOrder = false;
    }
    /**
     * Constructs an empty insertion-ordered <tt>LinkedHashMap</tt> instance
     * with the specified initial capacity and a default load factor (0.75).
     *
     * @param  initialCapacity the initial capacity
     * @throws IllegalArgumentException if the initial capacity is negative
     */
    public LinkedHashMap(int initialCapacity) {
        super(initialCapacity);
        accessOrder = false;
    }
    /**
     * Constructs an empty insertion-ordered <tt>LinkedHashMap</tt> instance
     * with the default initial capacity (16) and load factor (0.75).
     */
    public LinkedHashMap() {
        super();
        accessOrder = false;
    }
    /**
     * Constructs an insertion-ordered <tt>LinkedHashMap</tt> instance with
     * the same mappings as the specified map.  The <tt>LinkedHashMap</tt>
     * instance is created with a default load factor (0.75) and an initial
     * capacity sufficient to hold the mappings in the specified map.
     *
     * @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);
    }
    /**
     * Constructs an empty <tt>LinkedHashMap</tt> instance with the
     * specified initial capacity, load factor and ordering mode.
     *
     * @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;
    }
 
内部类
Entry
实际上是继承自HashMap.Node 静态内部类 ,我们知道HashMap.Node 实际上是一个单链表,因为它只有next 节点,但是这里LinkedHashMap.Entry保留了HashMap的数据结构,同时有before, after 两个节点,一个前驱节点一个后继节点,从而实现了双向链表
    /**
     * HashMap.Node subclass for normal LinkedHashMap entries.
     *  双向链表
     */
    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);
        }
    }
 
LinkedKeySet、LinkedValues 、LinkedEntrySet
**LinkedKeySet:**LinkedHashMap 的 key 集合
**LinkedValues:**LinkedHashMap 的 value 集合
LinkedEntrySet: LinkedHashMap 的 set 集合
结构都类似
    final class LinkedKeySet extends AbstractSet<K> {
        //元素个数
        public final int size()                 { return size; }
        //清空
        public final void clear()               { LinkedHashMap.this.clear(); }
        //key的迭代器
        public final Iterator<K> iterator() {
            return new LinkedKeyIterator();
        }
        //是否包含指定的key
        public final boolean contains(Object o) { return containsKey(o); }
        //通过key移除
        public final boolean remove(Object key) {
            return removeNode(hash(key), key, null, false, true) != null;
        }
        public final Spliterator<K> spliterator()  {
            return Spliterators.spliterator(this, Spliterator.SIZED |
                                            Spliterator.ORDERED |
                                            Spliterator.DISTINCT);
        }
        public final void forEach(Consumer<? super K> action) {
            if (action == null)
                throw new NullPointerException();
            int mc = modCount;
            for (LinkedHashMap.Entry<K,V> e = head; e != null; e = e.after)
                action.accept(e.key);
            if (modCount != mc)
                throw new ConcurrentModificationException();
        }
    }
 
LinkedHashIterator
LinkedHashMap 的元素遍历器
   abstract class LinkedHashIterator {
        //下个Node节点
        LinkedHashMap.Entry<K,V> next;
        //当前节点
        LinkedHashMap.Entry<K,V> current;
        //预期修改次数
        int expectedModCount;
        LinkedHashIterator() {
            next = head;
            expectedModCount = modCount;
            current = null;
        }
        public final boolean hasNext() {
            return next != null;
        }
        final LinkedHashMap.Entry<K,V> nextNode() {
            LinkedHashMap.Entry<K,V> e = next;
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
            if (e == null)
                throw new NoSuchElementException();
            current = e;
            next = e.after;
            return e;
        }
        public final void remove() {
            Node<K,V> p = current;
            if (p == null)
                throw new IllegalStateException();
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
            current = null;
            K key = p.key;
            removeNode(hash(key), key, null, false, false);
            expectedModCount = modCount;
        }
    }
 
LinkedKeyIterator、LinkedValueIterator、LinkedEntryIterator
继承了 LinkedHashIterator,只重写 next() 方法
    final class LinkedKeyIterator extends LinkedHashIterator
        implements Iterator<K> {
        public final K next() { return nextNode().getKey(); }
    }
    final class LinkedValueIterator extends LinkedHashIterator
        implements Iterator<V> {
        public final V next() { return nextNode().value; }
    }
    final class LinkedEntryIterator extends LinkedHashIterator
        implements Iterator<Map.Entry<K,V>> {
        public final Map.Entry<K,V> next() { return nextNode(); }
    }
 
常用方法
newNode
LinkedHashMap并没有重写任何put相关的方法,但其重写了构建节点的newNode方法;newNode方法会在putVal方法中被调用;putVal方法会在向集合中插入数据的时候被调用(单条插入put(K key, V value),批量插入putMapEntries(Map m, boolean evict))。
在每次构建新节点时,通过LinkedNodeLast方法将新节点链接在双向链表的尾部。
    Node<K,V> newNode(int hash, K key, V value, Node<K,V> e) {
        //创建Entry节点
        LinkedHashMap.Entry<K,V> p =
            new LinkedHashMap.Entry<K,V>(hash, key, value, e);
        //添加到尾部
        linkNodeLast(p);
        return p;
    }
 
linkNodeLast
    // link at the end of list
    //将指定entry插入到双向链表末尾
    private void linkNodeLast(LinkedHashMap.Entry<K,V> p) {
        LinkedHashMap.Entry<K,V> last = tail;
        //尾指针指向p
        tail = p;
        //如果原尾节点指向null,意味着双向循环链表为空,头尾指针都指向p
        if (last == null)
            head = p;
        else {
            //p的前驱节点指向原尾节点
            p.before = last;
            //原尾节点的后继节点指向p
            last.after = p;
        }
    }
 
clear
    /**
     * {@inheritDoc}
     * 清空map中元素
     */
    public void clear() {
        // 增加modcount,清除数组内元素
        super.clear();
        // 头等于尾等于null,代表链表为空
        head = tail = null;
    }
 
containsValue
    /**
     * Returns <tt>true</tt> if this map maps one or more keys to the
     * specified value.
     *
     * @param value value whose presence in this map is to be tested
     * @return <tt>true</tt> if this map maps one or more keys to the
     *         specified value
     *  查看是否包含某个元素
     */
    public boolean containsValue(Object value) {
        //从头到尾遍历双向链表
        for (LinkedHashMap.Entry<K,V> e = head; e != null; e = e.after) {
            V v = e.value;
            // 直接判断相等或者对象使用equals判断值相等时返回true
            if (v == value || (value != null && value.equals(v)))
                return true;
        }
        return false;
    }
 
keySet
    /**
     * Returns a {@link Set} view of the keys contained in this map.
     * The set is backed by the map, so changes to the map are
     * reflected in the set, and vice-versa.  If the map is modified
     * while an iteration over the set is in progress (except through
     * the iterator's own <tt>remove</tt> operation), the results of
     * the iteration are undefined.  The set supports element removal,
     * which removes the corresponding mapping from the map, via the
     * <tt>Iterator.remove</tt>, <tt>Set.remove</tt>,
     * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt>
     * operations.  It does not support the <tt>add</tt> or <tt>addAll</tt>
     * operations.
     * Its {@link Spliterator} typically provides faster sequential
     * performance but much poorer parallel performance than that of
     * {@code HashMap}.
     *
     * @return a set view of the keys contained in this map
     * 获取map的key值Set
     */
    public Set<K> keySet() {
        // 获取keySet
        Set<K> ks = keySet;
        if (ks == null) {
            // 实例化LinkedKeySet
            ks = new LinkedKeySet();
            keySet = ks;
        }
        return ks;
    }
 
values
    /**
     * Returns a {@link Collection} view of the values contained in this map.
     * The collection is backed by the map, so changes to the map are
     * reflected in the collection, and vice-versa.  If the map is
     * modified while an iteration over the collection is in progress
     * (except through the iterator's own <tt>remove</tt> operation),
     * the results of the iteration are undefined.  The collection
     * supports element removal, which removes the corresponding
     * mapping from the map, via the <tt>Iterator.remove</tt>,
     * <tt>Collection.remove</tt>, <tt>removeAll</tt>,
     * <tt>retainAll</tt> and <tt>clear</tt> operations.  It does not
     * support the <tt>add</tt> or <tt>addAll</tt> operations.
     * Its {@link Spliterator} typically provides faster sequential
     * performance but much poorer parallel performance than that of
     * {@code HashMap}.
     *
     * @return a view of the values contained in this map
     * 获取map的value值的集合
     */
    public Collection<V> values() {
        // 获取集合元素
        Collection<V> vs = values;
        if (vs == null) {
            // 实例化为LinkedValues
            vs = new LinkedValues();
            values = vs;
        }
        return vs;
    }
 
get
    /**
     * Returns the value to which the specified key is mapped,
     * or {@code null} if this map contains no mapping for the key.
     *
     * <p>More formally, if this map contains a mapping from a key
     * {@code k} to a value {@code v} such that {@code (key==null ? k==null :
     * key.equals(k))}, then this method returns {@code v}; otherwise
     * it returns {@code null}.  (There can be at most one such mapping.)
     *
     * <p>A return value of {@code null} does not <i>necessarily</i>
     * indicate that the map contains no mapping for the key; it's also
     * possible that the map explicitly maps the key to {@code null}.
     * The {@link #containsKey containsKey} operation may be used to
     * distinguish these two cases.
     */
    public V get(Object key) {
        Node<K,V> e;
        // 调用HashMap方法判断元素是否已经存在
        if ((e = getNode(hash(key), key)) == null)
            return null;
        // 当设置accessOrder时,将当前获取的元素放入
        if (accessOrder)
            afterNodeAccess(e);
        return e.value;
    }
 
afterNodeAccess
    /**
     *       第一种情况,插入节点是头节点
     *       a b c d e
     *       get(a),将a放到末尾
     *       b c d e a
     *       第二种情况,插入节点不是头节点
     *       a b c d e
     *       get(b),将b放到末尾
     *       a c d e b
     *
     *       将元素移动到最后一个
     * @param e
     */
    void afterNodeAccess(Node<K,V> e) { // move node to last
        LinkedHashMap.Entry<K,V> last;
        // 当需要排序并且加入节点e不是尾节点时,进入逻辑(为尾节点时,无需操作,已经为最近访问过的元素)
        if (accessOrder && (last = tail) != e) {
            // 首先暂存插入节点的当前节点,前节点,后节点
            LinkedHashMap.Entry<K,V> p =
                (LinkedHashMap.Entry<K,V>)e, b = p.before, a = p.after;
            // 将插入节点的后节点设为null,代表尾节点
            p.after = null;
            // 如果p的前置节点为null,代表插入节点p为头节点,p的后节点a就变为头节点
            // a  ...
            if (b == null)
                head = a;
            else
                // 不为空时, b的后指针指向a节点  b  a
                // b -> a
                b.after = a;
            // 插入节点的后一个节点不为null时,插入节点的后一个节点的前一个节点设置为插入节点的前一个节点  b  p a
            if (a != null)
                //a的上一个节点就变为b
                // b  <- a
                a.before = b;
            else
                //b为尾结点
                last = b;
            // 尾节点为null,代表链表为空,头节点直接设置为插入节点
            if (last == null)
                head = p;
            else {
                // 头节点的前置节点为尾节点
                p.before = last;
                // 尾节点的后一个节点为插入节点
                last.after = p;
            }
            // 新的尾节点设置为插入节点
            tail = p;
            // 增加修改数量
            ++modCount;
        }
    }
                













