Java_LinkedHashMap工作原理

Hash table and linked list implementation of the Map interface,with predictable iteration order. This implementation differs from HashMap in that it maintains a doubly-linked list running through all of its entries.

LinkedHashMap实现了Map接口,继承于HashMap,与HashMap不同的是它维持有一个双链表,从而可以保证迭代时候的顺序。

public class TestLinkedHashMap {
	public static void main(String[] args) {
		Map<String,String> map = new LinkedHashMap<String,String>();
		map.put("数学","数学老师");
		map.put("化学","化学老师");
		map.put("物理","物理老师");
		map.put("生物","生物老师");
		map.put("政治","政治老师");
		for(Entry<String, String> entry : map.entrySet()) {
			System.out.println(entry.getKey() + "-->" + entry.getValue());
		}
	}
}

这里写图片描述

可以看出LinkedhashMap在HashMap 基础上,用一个双向的链表维持的插入时候的顺序(默认,即accessOrder = false)。

public class TestLinkedHashMap {
	public static void main(String[] args) {
	//构造的时候 初始化容量为16,负载因子为0.75
	//第三个参数为accessOrder ,即迭代的顺序。有按插入的顺序和访问时的顺序。
	//默认为false,即按插入时候的顺序进行迭代。设置为true后,按访问时候的顺序进行迭代输出,即链表的最后一个元素总是最近才访问的。
Map<String,String> map = new LinkedHashMap<String,String>(16,0.75f,true);
		map.put("数学","数学老师");
		map.put("化学","化学老师");
		map.put("物理","物理老师");
		map.put("生物","生物老师");
		map.put("政治","政治老师");
		map.put("数学","数学老师");
		for(Entry<String, String> entry : map.entrySet()) {
			System.out.println(entry.getKey() + "-->" + entry.getValue());
		}
	}
}

此时调整链表如下:
这里写图片描述

LinkedHashMap部分源码:

    //链表第一个元素
    transient LinkedHashMap.Entry<K,V> head;
    //链表最后一个元素,当accessOrder = true的时候,表示最近使用的一个元素
    transient LinkedHashMap.Entry<K,V> tail;
    //迭代方式,默认为false,即按插入时候的方式进行迭代
    //若为true,即按访问时的顺序进行迭代
    final boolean accessOrder;
    
    //五种构造方法
     public LinkedHashMap(int initialCapacity, float loadFactor) {
        super(initialCapacity, loadFactor);
        //默认为false
        accessOrder = false;
    }

    
    public LinkedHashMap(int initialCapacity) {
        super(initialCapacity);
        accessOrder = false;
    }

    
    public LinkedHashMap() {
        super();
        accessOrder = false;
    }

   
    public LinkedHashMap(Map<? extends K, ? extends V> m) {
        super();
        accessOrder = false;
        putMapEntries(m, false);
    }

    //自定义accessOrder
    public LinkedHashMap(int initialCapacity,
                         float loadFactor,
                         boolean accessOrder) {
        super(initialCapacity, loadFactor);
        this.accessOrder = accessOrder;
    }
   ......
   
   //移除相应节点
   void afterNodeRemoval(Node<K,V> e) { // unlink
        LinkedHashMap.Entry<K,V> p =
            (LinkedHashMap.Entry<K,V>)e, b = p.before, a = p.after;
        p.before = p.after = null;
        if (b == null)
            head = a;
        else
            b.after = a;
        if (a == null)
            tail = b;
        else
            a.before = b;
    }

    //插入相应节点
    void afterNodeInsertion(boolean evict) { // possibly remove eldest
        LinkedHashMap.Entry<K,V> first;
        if (evict && (first = head) != null && removeEldestEntry(first)) {
            K key = first.key;
            removeNode(hash(key), key, null, false, true);
        }
    }

   //accessOrder = true的时候,保证最后一个节点是最近使用的
    void afterNodeAccess(Node<K,V> e) { // move node to last
        LinkedHashMap.Entry<K,V> last;
        if (accessOrder && (last = tail) != e) {
            LinkedHashMap.Entry<K,V> p =
                (LinkedHashMap.Entry<K,V>)e, b = p.before, a = p.after;
            p.after = null;
            if (b == null)
                head = a;
            else
                b.after = a;
            if (a != null)
                a.before = b;
            else
                last = b;
            if (last == null)
                head = p;
            else {
                p.before = last;
                last.after = p;
            }
            tail = p;
            ++modCount;
        }
    }
   
    //get
     public V get(Object key) {
        Node<K,V> e;
        if ((e = getNode(hash(key), key)) == null)
            return null;
        if (accessOrder)
            //按访问的顺序进行迭代,保证链表最后一个元素是最近使用的
            afterNodeAccess(e);
        //否则直接返回相应的值
        return e.value;
    }

总结:
LinkedHashMap是基于HashMap实现的,对于HashMap有认识,理解LinkedHashMap应该不难.LinkedHashMap使用一个双向链表对键值度进行维护,创建LinkedHashMap的时候,默认accessOrder=false,迭代的时候为插入时候的顺序,只有第五种构造方法:

 public LinkedHashMap(int initialCapacity,
                         float loadFactor,
                         boolean accessOrder) {....}

可以使其迭代的方式变为按访问时候的顺序。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章