标签:android des style blog http color java strong
在Android开发过程中,遇到需要处理大量图片显示问题时,需要运用缓存机制。而Java中已经为我们提供了很好的工具LinkedHashMap,为我们实现LRU算法提供了很大的便利。下面结合LinkedHashMap源码来了解其原理。
1.LinkedHashMap结构
LinkedHashMap继承了HashMap底层是通过Hash表+单向链表实现Hash算法,内部自己维护了一套元素访问顺序的列表。
LinkedHashMap与HashMap的区别是在于LinkeedHashMap每个元素插入表中时,就会并入到双向链表中。此链接列表定义了迭代顺序,该迭代顺序可以是插入顺序或者是访问顺序。当访问顺序时,每次调用get或者put,受到影响的条目将从当前的位置删除,并放到链表条目的尾部,在这里只是链表中位置变化受到影响,而散列表中的桶不会受影响。
2.LinkedHashMap实现
2.1记录顺序
Linked内部含有一个private transient Entry header;来记录元素插入的顺序或者是元素被访问的顺序。
决定记录顺序的是由初始化时private final boolean accessOrder;
AccessOrder。默认为false,即插入顺序,true为访问顺序。
2.2构造函数
1 public LinkedHashMap(int initialCapacity, 2 float loadFactor, 3 boolean accessOrder) { 4 super(initialCapacity, loadFactor); 5 this.accessOrder = accessOrder; 6 }
initialCapacity是初始化表的大小,loadFactor是装载因子,默认0.75,accessOrder是指定记录的顺序,访问顺序还是插入顺序。后面的true表明LinkedHashMap按照访问的次序来排序。按照访问的次序来排序的含义:当调用LinkedHashMap的get(key)或者put(key, value)时,碰巧key在map中被包含,那么LinkedHashMap会将key对象的entry放在线性结构的最后。按照插入顺序来排序的含义:调用get(key), 或者put(key, value)并不会对线性结构产生任何的影响。
2.3获取记录
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 }
如果key存在,执行recordAccess(this);
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 }
recordAccess方法会accessOrder为true会先调用remove清除当前首尾元素的指向关系,之后调用addBefore方法,将当前元素加入header之前。
1 /** 2 * Removes this entry from the linked list. 3 */ 4 private void remove() { 5 before.after = after; 6 after.before = before; 7 } 8 9 /** 10 * Inserts this entry before the specified existing entry in the list. 11 */ 12 private void addBefore(Entry<K,V> existingEntry) { 13 after = existingEntry; 14 before = existingEntry.before; 15 before.after = this; 16 after.before = this; 17 }
2.4获取数据
LinkedHashMap put方法时继承HashMap的put方法,但是需要重写其中的方法
1 public V put(K key, V value) { 2 if (key == null) 3 return putForNullKey(value); 4 int hash = hash(key.hashCode()); 5 int i = indexFor(hash, table.length); 6 for (Entry<K,V> e = table[i]; e != null; e = e.next) { 7 Object k; 8 if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { 9 V oldValue = e.value; 10 e.value = value; 11 e.recordAccess(this); 12 return oldValue; 13 } 14 } 15 16 modCount++; 17 addEntry(hash, key, value, i); 18 return null; 19 }
2.5删除最久未被访问数据
1 protected boolean removeEldestEntry(Map.Entry eldest) { 2 return false; 3 }
LinkedHashMap中一个方法,当调用put(key, value)的时候,HashMap判断是否要自动增加map的size的作法是判断是否超过threshold, LinkedHashMap则进行了扩展,如果removeEldestEntry方法return false;(默认的实现),那么LinkedHashMap跟HashMap处理扩容的方式一致;如果removeEldestEntry返回 true,那么LinkedHashMap会自动删掉最不常用的那个entry(也就是header线性表最前面的那个)。这一特点可以很好实现缓存机制。
3.缓存机制简单实现
1 import java.util.Iterator; 2 import java.util.LinkedHashMap; 3 4 public class LRULinkedHashMap<K,V> extends LinkedHashMap<K, V>{ 5 6 private static final int INIT_CAPACITY=10; 7 private static final int MAX_SIZE=6; 8 private static final float LOAD_FACTOR=0.75f; 9 10 public LRULinkedHashMap() { 11 super(INIT_CAPACITY, LOAD_FACTOR, true); 12 } 13 14 @Override 15 protected boolean removeEldestEntry(java.util.Map.Entry<K, V> eldest) { 16 return size()>MAX_SIZE; 17 } 18 19 public static void main(String[] args) { 20 21 LRULinkedHashMap<String, String> lruLinkedHashMap=new LRULinkedHashMap<String,String>(); 22 lruLinkedHashMap.put("1", "A"); 23 lruLinkedHashMap.put("2", "B"); 24 lruLinkedHashMap.put("3", "C"); 25 lruLinkedHashMap.put("4", "D"); 26 lruLinkedHashMap.put("5", "E"); 27 lruLinkedHashMap.put("6", "F"); 28 lruLinkedHashMap.put("7", "G"); 29 lruLinkedHashMap.put("8", "H"); 30 lruLinkedHashMap.put("9", "I"); 31 lruLinkedHashMap.put("10", "J"); 32 lruLinkedHashMap.put("11", "K"); 33 Iterator<String> iterator=lruLinkedHashMap.keySet().iterator(); 34 while(iterator.hasNext()){ 35 System.out.print(iterator.next()+" "); 36 } 37 } 38 39 }
结果显示:
6 7 8 9 10 11
Java技术之LinkedHashMap,布布扣,bubuko.com
标签:android des style blog http color java strong
原文地址:http://www.cnblogs.com/forsta/p/3886891.html