码迷,mamicode.com
首页 > 编程语言 > 详细

Java技术之LinkedHashMap

时间:2014-08-02 15:16:43      阅读:382      评论:0      收藏:0      [点我收藏+]

标签:android   des   style   blog   http   color   java   strong   

     在Android开发过程中,遇到需要处理大量图片显示问题时,需要运用缓存机制。而Java中已经为我们提供了很好的工具LinkedHashMap,为我们实现LRU算法提供了很大的便利。下面结合LinkedHashMap源码来了解其原理。

1.LinkedHashMap结构

LinkedHashMap继承了HashMap底层是通过Hash表+单向链表实现Hash算法,内部自己维护了一套元素访问顺序的列表。

bubuko.com,布布扣

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

Java技术之LinkedHashMap

标签:android   des   style   blog   http   color   java   strong   

原文地址:http://www.cnblogs.com/forsta/p/3886891.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!