标签:作用 维护 等等 位置 div record 代码 enter 散列
public class LinkedHashMap<K,V>
                  extends HashMap<K,V>
                  implements Map<K,V>//双向循环链表的头结点 private transient Entry<K,V> header; //accessOrder代表链表的排序方式;true为按照访问顺序,false为插入顺序。 private final boolean accessOrder;
           //按指定的初始化容量和加载因子,生成一个空的LinkedHashMap,
	  //默认将accessOrder设为false,按插入顺序排序.
	    public LinkedHashMap(int initialCapacity, float loadFactor) {
	        super(initialCapacity, loadFactor);
	        accessOrder = false;//默认设为插入顺序
	    }
	    //按指定初始化容量,生成一个LinkedHashMap构造器;默认加载因子为0.75
	  //默认将accessOrder设为false,按插入顺序排序.
	    public LinkedHashMap(int initialCapacity) {
	        super(initialCapacity);
	        accessOrder = false;//默认设为插入顺序
	    }
	    //生成一个LinkedHashMap构造器;默认加载因子为0.75,初始化容量为16
	  //默认将accessOrder设为false,按插入顺序排序.
	    public LinkedHashMap() {
	        super();
	        accessOrder = false;
	    }
	    //根据指定的map生成一个新的HashMap,负载因子使用默认值,初始容量大小为Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1,DEFAULT_INITIAL_CAPACITY)
	     //默认将accessOrder设为false,按插入顺序排序.
	    public LinkedHashMap(Map<? extends K, ? extends V> m) {
	        super(m);
	        accessOrder = false;
	    }
	    //按指定初始化容量,加载因子,链表的排序方式生成一个LinkedHashMap构造器
	    public LinkedHashMap(int initialCapacity,
	                         float loadFactor,
	                         boolean accessOrder) {
	        super(initialCapacity, loadFactor);
	        this.accessOrder = accessOrder;
	    }
   构造器首先都会调用父类也就是HashMap的构造器来初始化桶数组,而accessOrder之后会被初始化,   
除了最后面的一个构造器允许指定accessOrder外,其他构造器都 默认将accessOrder置为了false 。public HashMap(int initialCapacity, float loadFactor) {
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal initial capacity: " +
                                               initialCapacity);
       ... ...
        init();
    }
HashMap构造器最后一步调用了一个init方法,而这个init方法在HashMap中是个空实现,没有任何代码。 /**
	     * 覆盖HashMap的init方法,在构造方法、Clone、readObject方法里会调用该方法
	     * 作用是生成一个双向链表头节点,初始化其前后节点引用
	     */
	    @Override
	    void init() {
	        header = new Entry<>(-1, null, null, null);//初始化双向链表
	        header.before = header.after = header;//不光是双向链表,还是循环链表
	    }
//LinkedHashMap节点对象 private static class Entry<K,V> extends HashMap.Entry<K,V> { // These fields comprise the doubly linked list used for iteration. Entry<K,V> before, after;//前后指针 //构造函数 Entry(int hash, K key, V value, HashMap.Entry<K,V> next) { super(hash, key, value, next); } //移除此节点,并修改前后的引用 private void remove() { before.after = after; after.before = before; } //将当前结点(this)插入到existingEntry结点前 private void addBefore(Entry<K,V> existingEntry) { after = existingEntry;//先获取existingEntry的前后节点 before = existingEntry.before; before.after = this;//双向指针,都需要修改 after.before = this; } /** * 在父类HashMap中的get,set方法会调用此方法recordAccess; * 在LinkedHashMap中,当按访问顺序排序时,该方法会将当前节点插入到链表尾部(头结点的前一个节点) * 否则不做任何事 */ void recordAccess(HashMap<K,V> m) { LinkedHashMap<K,V> lm = (LinkedHashMap<K,V>)m; if (lm.accessOrder) {//当按访问顺序排序时 lm.modCount++; remove();//移除当前节点 addBefore(lm.header);//将当前节点插入到头结点前面 } } void recordRemoval(HashMap<K,V> m) { remove(); } }
public V put(K key, V value) {//HashMap的put方法
		if (key == null)
			return putForNullKey(value);
		int hash = hash(key);
		int i = indexFor(hash, table.length);
		for (Entry<K,V> e = table[i]; e != null; e = e.next) {
			Object k;
			if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
				V oldValue = e.value;
				e.value = value;
				e.recordAccess(this);//发生覆盖操作时,会调用此方法
				return oldValue;
			}
		}
	  ... ...
	}此外,在LinkedHashMap的get方法中,也会调用此方法: //根据指定key返回value:先得到entry结点,再返回其值;调用的是HashMap的getEntry方法
	    //与HashMap的区别是:当LinkedHashMap按访问顺序排序的时候,会将访问的当前节点移到链表尾部(头结点的前一个节点)
	    public V get(Object key) {
	        Entry<K,V> e = (Entry<K,V>)getEntry(key);
	        if (e == null)
	            return null;
	        e.recordAccess(this);
	        return e.value;
	    }
也就是说,只要涉及到访问结点,那么就会调用这个方法。 观察该方法的逻辑:
如果accessOrder为true,/** * 创建节点,插入到LinkedHashMap,该方法覆盖HashMap的addEntry方法 */ void addEntry(int hash, K key, V value, int bucketIndex) { super.addEntry(hash, key, value, bucketIndex); // eldest:头结点的下个节点header.after,存放于链表头部,是最不经常访问或第一个插入的节点, Entry<K,V> eldest = header.after; //有必要的情况下(如容量不够,具体看removeEldestEntry方法的实现,这里默认为false,不删除),可以先删除 if (removeEldestEntry(eldest)) { removeEntryForKey(eldest.key); } } /** * 创建节点,并将该节点插入到链表尾部 */ void createEntry(int hash, K key, V value, int bucketIndex) { HashMap.Entry<K,V> old = table[bucketIndex]; Entry<K,V> e = new Entry<>(hash, key, value, old); table[bucketIndex] = e; e.addBefore(header);//节点插入到链表尾部 size++; }createEntry方法会将键值对分别挂到桶数组和双向链表中。
 //迭代器
	    private abstract class LinkedHashIterator<T> implements Iterator<T> {
	        Entry<K,V> nextEntry    = header.after;
	        Entry<K,V> lastReturned = null;
	        //用于迭代期间快速失败行为
	        int expectedModCount = modCount;
	        
	        //判断是否还有下个节点;当为头结点的时候说明没有下个节点即返回false
	        public boolean hasNext() {
	            return nextEntry != header;
	        }
	        //移除当前访问的节点
	        public void remove() {
	            if (lastReturned == null)
	                throw new IllegalStateException();
	            if (modCount != expectedModCount)
	                throw new ConcurrentModificationException();
	            LinkedHashMap.this.remove(lastReturned.key);
	            lastReturned = null;
	            expectedModCount = modCount;
	        }
	        Entry<K,V> nextEntry() {
	            if (modCount != expectedModCount)
	                throw new ConcurrentModificationException();
	            if (nextEntry == header)
	                throw new NoSuchElementException();
	            Entry<K,V> e = lastReturned = nextEntry;
	            nextEntry = e.after;
	            return e;
	        }
	    }/**
	 * LinkedHashMap接口是的Map接口哈希表和链接列表的实现,
	 * 具有可预知的迭代顺序。这个实现类与HashMap不同之处在于其所有结点都之间以双链表进行维护。
	 * 此链表定义了迭代顺序,此顺序通常就是按键插入到映射中的顺序(插入顺序)。
	 * 注意:如果在映射中重新插入键,则插入顺序不受影响。
	 * 允许null元素;
	 * 增加了维护链接列表的开支,性能比HashMap稍逊;
	 * 此实现不是同步的,改为同步:
	 * 		Map m = Collections.synchronizedMap(new LinkedHashMap());
	 * 
	 */
	public class LinkedHashMap<K,V>
						extends HashMap<K,V>
	    				implements Map<K,V>
	{
	    private static final long serialVersionUID = 3801124242820219131L;
	    //双向循环链表的头结点
	    private transient Entry<K,V> header;
	    //accessOrder代表链表的排序方式;true为按照访问顺序,false为插入顺序。
	    private final boolean accessOrder;
	    //按指定的初始化容量和加载因子,生成一个空的LinkedHashMap,
	  //默认将accessOrder设为false,按插入顺序排序.
	    public LinkedHashMap(int initialCapacity, float loadFactor) {
	        super(initialCapacity, loadFactor);
	        accessOrder = false;//默认设为插入顺序
	    }
	    //按指定初始化容量,生成一个LinkedHashMap构造器;默认加载因子为0.75
	  //默认将accessOrder设为false,按插入顺序排序.
	    public LinkedHashMap(int initialCapacity) {
	        super(initialCapacity);
	        accessOrder = false;//默认设为插入顺序
	    }
	    //生成一个LinkedHashMap构造器;默认加载因子为0.75,初始化容量为16
	  //默认将accessOrder设为false,按插入顺序排序.
	    public LinkedHashMap() {
	        super();
	        accessOrder = false;
	    }
	    //根据指定的map生成一个新的HashMap,负载因子使用默认值,初始容量大小为Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1,DEFAULT_INITIAL_CAPACITY)
	     //默认将accessOrder设为false,按插入顺序排序.
	    public LinkedHashMap(Map<? extends K, ? extends V> m) {
	        super(m);
	        accessOrder = false;
	    }
	    //按指定初始化容量,加载因子,链表的排序方式生成一个LinkedHashMap构造器
	    public LinkedHashMap(int initialCapacity,
	                         float loadFactor,
	                         boolean accessOrder) {
	        super(initialCapacity, loadFactor);
	        this.accessOrder = accessOrder;
	    }
	    /**
	     * 覆盖HashMap的init方法,在构造方法、Clone、readObject方法里会调用该方法
	     * 作用是生成一个双向链表头节点,初始化其前后节点引用
	     */
	    @Override
	    void init() {
	        header = new Entry<>(-1, null, null, null);//初始化双向链表
	        header.before = header.after = header;//不光是双向链表,还是循环链表
	    }
	    /**
	     * 覆盖HashMap的transfer方法,性能优化,这里遍历方式不采用HashMap的双重循环方式
	     * 而是直接通过双向链表遍历Map中的所有key-value映射
	     */
	    @Override
	    void transfer(HashMap.Entry[] newTable, boolean rehash) {
	        int newCapacity = newTable.length;//获取新表大小
	        //遍历旧Map中的所有key-value
	        for (Entry<K,V> e = header.after; e != header; e = e.after) {
	            //看是否需要进行再哈希操作,需要的话就重新计算key的哈希值
	        	if (rehash)
	                e.hash = (e.key == null) ? 0 : hash(e.key);
	            int index = indexFor(e.hash, newCapacity);//根据数组长度重新计算索引
	            e.next = newTable[index];//插入到链表表头
	            newTable[index] = e;//将e放到索引为i的数组处
	        }
	    }
	    //判断是否含有值value
	    //与HashMap不同地方在于是直接遍历链表进行查询获取,而不用计算key的hash值去寻找桶再遍历
	    public boolean containsValue(Object value) {
	        // Overridden to take advantage of faster iterator
	        if (value==null) {
	            for (Entry e = header.after; e != header; e = e.after)
	                if (e.value==null)
	                    return true;
	        } else {
	            for (Entry e = header.after; e != header; e = e.after)
	                if (value.equals(e.value))
	                    return true;
	        }
	        return false;
	    }
	    //根据指定key返回value:先得到entry结点,再返回其值;调用的是HashMap的getEntry方法
	    //与HashMap的区别是:当LinkedHashMap按访问顺序排序的时候,会将访问的当前节点移到链表尾部(头结点的前一个节点)
	    public V get(Object key) {
	        Entry<K,V> e = (Entry<K,V>)getEntry(key);
	        if (e == null)
	            return null;
	        e.recordAccess(this);
	        return e.value;
	    }
	    //清空链表:调用的父类clear方法
	    public void clear() {
	        super.clear();
	        header.before = header.after = header;
	    }
	    //LinkedHashMap节点对象
	    private static class Entry<K,V> extends HashMap.Entry<K,V> {
	        // These fields comprise the doubly linked list used for iteration.
	        Entry<K,V> before, after;//前后指针
	        //构造函数
	        Entry(int hash, K key, V value, HashMap.Entry<K,V> next) {
	            super(hash, key, value, next);
	        }
	        //移除此节点,并修改前后的引用
	        private void remove() {
	            before.after = after;
	            after.before = before;
	        }
	        //将当前结点(this)插入到existingEntry结点前
	        private void addBefore(Entry<K,V> existingEntry) {
	            after  = existingEntry;//先获取existingEntry的前后节点
	            before = existingEntry.before;
	            before.after = this;//双向指针,都需要修改
	            after.before = this;
	        }
	        /**
	         * 在父类HashMap中的get,set方法会调用此方法recordAccess;
	         * 在LinkedHashMap中,当按访问顺序排序时,该方法会将当前节点插入到链表尾部(头结点的前一个节点)
	         * 否则不做任何事
	         */
	        void recordAccess(HashMap<K,V> m) {
	            LinkedHashMap<K,V> lm = (LinkedHashMap<K,V>)m;
	            if (lm.accessOrder) {//当按访问顺序排序时
	                lm.modCount++;
	                remove();//移除当前节点
	                addBefore(lm.header);//将当前节点插入到头结点前面
	            }
	        }
	        void recordRemoval(HashMap<K,V> m) {
	            remove();
	        }
	    }
	    //迭代器
	    private abstract class LinkedHashIterator<T> implements Iterator<T> {
	        Entry<K,V> nextEntry    = header.after;
	        Entry<K,V> lastReturned = null;
	        //用于迭代期间快速失败行为
	        int expectedModCount = modCount;
	        
	        //判断是否还有下个节点;当为头结点的时候说明没有下个节点即返回false
	        public boolean hasNext() {
	            return nextEntry != header;
	        }
	        //移除当前访问的节点
	        public void remove() {
	            if (lastReturned == null)
	                throw new IllegalStateException();
	            if (modCount != expectedModCount)
	                throw new ConcurrentModificationException();
	            LinkedHashMap.this.remove(lastReturned.key);
	            lastReturned = null;
	            expectedModCount = modCount;
	        }
	        Entry<K,V> nextEntry() {
	            if (modCount != expectedModCount)
	                throw new ConcurrentModificationException();
	            if (nextEntry == header)
	                throw new NoSuchElementException();
	            Entry<K,V> e = lastReturned = nextEntry;
	            nextEntry = e.after;
	            return e;
	        }
	    }
	    //key迭代器
	    private class KeyIterator extends LinkedHashIterator<K> {
	        public K next() { return nextEntry().getKey(); }
	    }
	    //value迭代器
	    private class ValueIterator extends LinkedHashIterator<V> {
	        public V next() { return nextEntry().value; }
	    }
	    //key-value迭代器
	    private class EntryIterator extends LinkedHashIterator<Map.Entry<K,V>> {
	        public Map.Entry<K,V> next() { return nextEntry(); }
	    }
	    // 返回不同的迭代器对象
	    Iterator<K> newKeyIterator()   { return new KeyIterator();   }
	    Iterator<V> newValueIterator() { return new ValueIterator(); }
	    Iterator<Map.Entry<K,V>> newEntryIterator() { return new EntryIterator(); }
	    /**
	     * 创建节点,插入到LinkedHashMap,该方法覆盖HashMap的addEntry方法
	     */
	    void addEntry(int hash, K key, V value, int bucketIndex) {
	        super.addEntry(hash, key, value, bucketIndex);
	        // eldest:头结点的下个节点header.after,存放于链表头部,是最不经常访问或第一个插入的节点,
	        Entry<K,V> eldest = header.after;
	        //有必要的情况下(如容量不够,具体看removeEldestEntry方法的实现,这里默认为false,不删除),可以先删除
	        if (removeEldestEntry(eldest)) {
	            removeEntryForKey(eldest.key);
	        }
	    }
	    /**
	     * 创建节点,并将该节点插入到链表尾部
	     */
	    void createEntry(int hash, K key, V value, int bucketIndex) {
	        HashMap.Entry<K,V> old = table[bucketIndex];
	        Entry<K,V> e = new Entry<>(hash, key, value, old);
	        table[bucketIndex] = e;
	        e.addBefore(header);//节点插入到链表尾部
	        size++;
	    }
	    /**
	     * 该方法在创建新节点的时候调用,
	     * 判断是否有必要删除链表头部的第一个节点(最不经常访问或最先插入的节点,由accessOrder决定)
	     */
	    protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {
	        return false;
	    }
	}【JDK源码阅读9-util】LinkedHashMap接口
标签:作用 维护 等等 位置 div record 代码 enter 散列
原文地址:http://blog.csdn.net/noaman_wgs/article/details/53138604