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) {....}

可以使其迭代的方式變爲按訪問時候的順序。

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