JDK LinkedHashMap的源代码解析

今天来分析一下JDK  LinkedHashMap的源代码

 

Java代码   收藏代码
  1. public class LinkedHashMap<K,V>  
  2.     extends HashMap<K,V>  
  3.     implements Map<K,V>  

 可以看到,LinkedHashMap继承自HashMap,并且也实现了Map接口,所以LinkedHashMap沿用了HashMap的大多数方法

,包括构造方法也调用了父类HashMap的构造方法:

 

Java代码   收藏代码
  1. public LinkedHashMap(int initialCapacity, float loadFactor) {  
  2.         super(initialCapacity, loadFactor);  
  3.         accessOrder = false;  
  4.     }  
  5.   
  6.      
  7.     public LinkedHashMap(int initialCapacity) {  
  8.     super(initialCapacity);  
  9.         accessOrder = false;  
  10.     }  
  11.   
  12.      
  13.     public LinkedHashMap() {  
  14.     super();  
  15.         accessOrder = false;  
  16.     }  
  17.   
  18.      
  19.     public LinkedHashMap(Map<? extends K, ? extends V> m) {  
  20.         super(m);  
  21.         accessOrder = false;  
  22.     }  
  23.   
  24.      
  25.     public LinkedHashMap(int initialCapacity,  
  26.              float loadFactor,  
  27.                          boolean accessOrder) {  
  28.         super(initialCapacity, loadFactor);  
  29.         this.accessOrder = accessOrder;  
  30.     }  

 但是昨天在分析HashMap的时候说过HashMap的init方法没有实现,但是LinkedHaqshMap已经对其实现:

 

Java代码   收藏代码
  1. void init() {  
  2.         header = new Entry<K,V>(-1nullnullnull);//初始化一个Entry类型的header  
  3.         header.before = header.after = header;  
  4.     }  

 在LinkedHashMap中多了一个accessOrder变量,他表示迭代时候的一个顺序,若为true,则按照读取顺序排序(读得越多在链表的越后面,读得越少在链表的越前面,LRU,最近最少使用),若为false则按照插入顺序排序.从LinkedHaqshMap的前4个构造方法可以看出,accessOrder默认为false,故按照插入顺序进行排序.

 

Java代码   收藏代码
  1. public V get(Object key) {  
  2.        Entry<K,V> e = (Entry<K,V>)getEntry(key);  
  3.        if (e == null)  
  4.            return null;  
  5.        e.recordAccess(this);  
  6.        return e.value;  
  7.    }  

 getEntry()HashMap里的实现:

java代码   收藏代码
  1.     final Entry<K,V> getEntry(Object key) {
            int hash = (key == null) ? 0 : hash(key.hashCode());
            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;
        }


 在这个get方法中要注意recordAccess这个方法:

 

Java代码   收藏代码
  1. void recordAccess(HashMap<K,V> m) {  
  2.            LinkedHashMap<K,V> lm = (LinkedHashMap<K,V>)m;  
  3.            if (lm.accessOrder) {  
  4.                lm.modCount++;  
  5.                remove();  
  6.                addBefore(lm.header);  
  7.            }  
  8.        }  

 这个方法定义在LinkedHashMap的内部类Entry中,他判断accessOrder属性,若为true,则执行一个叫做LRU的算法

该算法的中文名称叫做最近最少使用算法,他通过将刚访问的entry移除,然后加到header前面,这样迭代的时候会优先迭代

最近频繁访问的entry,从而就改变了迭代的顺序

对于put方法,LinkedHashMap也实现了父类HashMap没有实现的recordAccess,并重写了addEntry方法,虽然在LinkedHashMap没有重写put方法

 

Java代码   收藏代码
  1. void addEntry(int hash, K key, V value, int bucketIndex) {  
  2.         createEntry(hash, key, value, bucketIndex);//在header前构造一个entry  
  3.       
  4.         Entry<K,V> eldest = header.after;//找到最老的一个元素  
  5.         if (removeEldestEntry(eldest)) {  
  6.             removeEntryForKey(eldest.key);  
  7.         } else {  
  8.             if (size >= threshold)  
  9.                 resize(2 * table.length);  
  10.         }  
  11.     }  

 可以看到该方法会删除最老的一个元素,removeEldestEntry是一个受保护的方法,用来确定是否满足删除条件,可以重写它实现自己的策略,默认该方法返回false

当然,可以通过覆盖该方法,加入一定的条件,如果条件满足则返回true.如:

protected boolean removeEldestEntry(Map.Entry eldest) {
        return size() > MAX_ENTRIES;
     }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值