d.linkedhashMap源码解析(1.7)

相对而言,linkedhashMap要比TreeMap更加重要

有一些逻辑以及LRU算法值得深究

在于与普通的哈希Map的比较时,特点是内部维护的双向链表,可以记录顺序(访问顺序,或插入顺序)

public class LinkedHashMap<K,V>
    extends HashMap<K,V>
    implements Map<K,V>

看类的声明,可以注意的是linkedhashMap是哈希Map的子类,也重写了在Hashmap里面的有一些有空方法体的方法

属性

  //作为LinkedhashMap,用链表来维护一个顺序
    private transient Entry<K,V> header;
  //访问顺序,也就是涉及到以后用到的LRU,true:按照访问顺序,false:按照插入顺序
    private final boolean accessOrder;


  //继承了哈希Map的Entry,作为双向链表的节点
    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;
        }


        private void addBefore(Entry<K,V> existingEntry) {
            after  = existingEntry;
            before = existingEntry.before;
            before.after = this;
            after.before = this;
        }

     //如果记录访问顺序,则将此元素记录在header之前
        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();
        }
    }
</pre><pre name="code" class="java">

构造方法

  //五个构造函数,总体来说是要有加载因子初始容量以及加载因子,并且默认关闭LRU
   public LinkedHashMap(int initialCapacity, float loadFactor) {
        super(initialCapacity, loadFactor);
        accessOrder = false;
    }

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

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

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

  
    public LinkedHashMap(int initialCapacity,
                         float loadFactor,
                         boolean accessOrder) {
        super(initialCapacity, loadFactor);
        this.accessOrder = accessOrder;
    }
 LinkedHashMap是基于双向链表的,而且属性中定了一个header节点

初始化

  void init() {
        header = new Entry<>(-1, null, null, null);
        header.before = header.after = header;
    }


transfer,旧数组到新数组

 @Override
    void transfer(HashMap.Entry[] newTable, boolean rehash) {
        int newCapacity = newTable.length;
        for (Entry<K,V> e = header.after; e != header; e = e.after) {
            if (rehash)//如果需要重新哈希的话
                e.hash = (e.key == null) ? 0 : hash(e.key);
            int index = indexFor(e.hash, newCapacity);//计算位置
            e.next = newTable[index];//倒序放置
            newTable[index] = e;
        }
    }

   //包含Value
    public boolean containsValue(Object value) {
        // Overridden to take advantage of faster iterator
        if (value==null) {//找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;
    }


get

 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;
    }
 //getEntry,找到bucket,然后遍历
 final Entry<K,V> getEntry(Object key) {
        if (size == 0) {
            return null;
        }

        int hash = (key == null) ? 0 : hash(key);
        for (Entry<K,V> e = table[indexFor(hash, table.length)];
             e != null;
             e = e.next) {
            Object k;
            if (e.hash == hash &&
                ((k = e.key) == key || (key != null && key.equals(k))))
                return e;
        }
        return null;
    }
//获取哈希值
 final int hash(Object k) {
        int h = hashSeed;
        if (0 != h && k instanceof String) {
            return sun.misc.Hashing.stringHash32((String) k);
        }

        h ^= k.hashCode();

        // This function ensures that hashCodes that differ only by
        // constant multiples at each bit position have a bounded
        // number of collisions (approximately 8 at default load factor).
        h ^= (h >>> 20) ^ (h >>> 12);
        return h ^ (h >>> 7) ^ (h >>> 4);
    }

记录访问
 void recordAccess(HashMap<K,V> m) {
            LinkedHashMap<K,V> lm = (LinkedHashMap<K,V>)m;
            if (lm.accessOrder) {//如果true,记录访问顺序
                lm.modCount++;
                remove();
                addBefore(lm.header); //根据LRU算法,使用过的最后被取出,也就是加在链表的最后,首先遍历取出来的是用的最少的
            }
        }

迭代器重写了,这里使用header开始迭代,顺序遍历,稍微看一下 expectedModCount,另外,这里只能删除,不提供别的方法
 private abstract class LinkedHashIterator<T> implements Iterator<T> {
        Entry<K,V> nextEntry    = header.after;
        Entry<K,V> lastReturned = null;

        /**
         * The modCount value that the iterator believes that the backing
         * List should have.  If this expectation is violated, the iterator
         * has detected concurrent modification.
         */
        int expectedModCount = modCount;

        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;
        }
    }







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值