LruCache原理分析
来源:互联网 发布:windows vista和win7 编辑:程序博客网 时间:2024/06/06 01:55
LinkedHashMap原理分析
一.实现
LinkedHashMap继承HashMap数据结构:HashMapEntry(key,value)--》LinkedHashMapEntry(key,value+before指针和after指针(双向链表))1.构造函数LinkedHashMap/* accessOrder true if the ordering should be done based on the last access (from least-recently accessed to most-recently accessed), and false if the ordering should be the order in which the entries were inserted.*/public LinkedHashMap( int initialCapacity, float loadFactor, boolean accessOrder) { super(initialCapacity, loadFactor); init(); this.accessOrder = accessOrder;}super(initialCapacity, loadFactor) { // 新建一个HashMap-->创建HashMap对应的集合 ...}@Override void init() { header = new LinkedEntry<K, V>();}/* LinkedEntry是双向链表+HashMap的item LinkedEntry是HashMapEntry的子类 HashMapEntry是HashMap的item*/static class LinkedEntry<K, V> extends HashMapEntry<K, V> { LinkedEntry<K, V> nxt; LinkedEntry<K, V> prv; /** Create the header entry */ LinkedEntry() { super(null, null, 0, null); nxt = prv = this; } /** Create a normal entry */ LinkedEntry(K key, V value, int hash, HashMapEntry<K, V> next, LinkedEntry<K, V> nxt, LinkedEntry<K, V> prv) { super(key, value, hash, next);// 调用HashMap的构造函数 this.nxt = nxt; this.prv = prv; }}2.put函数--同HashMap的put函数// 覆写该函数// 修改已经put进去的key对应的value的时候会调用该函数@Override void preModify(HashMapEntry<K, V> e) { if (accessOrder) { makeTail((LinkedEntry<K, V>) e); }}// 将e元素插入到循环双向链表的末尾(如果之前已经插入到循环双向链表中,则删除,然后插入到末尾)/*** Relinks the given entry to the tail of the list. Under access ordering,* this method is invoked whenever the value of a pre-existing entry is* read by Map.get or modified by Map.put.*/private void makeTail(LinkedEntry<K, V> e) {// Tail:尾巴 // Unlink e e.prv.nxt = e.nxt; e.nxt.prv = e.prv; // header是LinkedEntry的链表,LinkedEntry在1构造函数中有介绍 // Relink e as tail LinkedEntry<K, V> header = this.header; // 将e插入到循环双向链表的最后一个元素 LinkedEntry<K, V> oldTail = header.prv; e.nxt = header; e.prv = oldTail; oldTail.nxt = header.prv = e; modCount++;}// 覆写该函数--相当于调用makeTail,把item插入到双向队列的末尾@Override void addNewEntry(K key, V value, int hash, int index) { LinkedEntry<K, V> header = this.header; // Remove eldest entry if instructed to do so. LinkedEntry<K, V> eldest = header.nxt; if (eldest != header && removeEldestEntry(eldest)) { remove(eldest.key); } // Create new entry, link it on to list, and put it into table LinkedEntry<K, V> oldTail = header.prv; LinkedEntry<K, V> newTail = new LinkedEntry<K,V>(key, value, hash, table[index], header, oldTail); table[index] = oldTail.nxt = header.prv = newTail;}3.get函数// 该实现和HashMap的get函数实现几乎一样,除了注释的那句代码外@Override public V get(Object key) { ... // Replace with Collections.secondaryHash when the VM is fast enough (http://b/8290590). int hash = secondaryHash(key); HashMapEntry<K, V>[] tab = table; // HashMap.java的table for (HashMapEntry<K, V> e = tab[hash & (tab.length - 1)]; e != null; e = e.next) { K eKey = e.key; if (eKey == key || (e.hash == hash && key.equals(eKey))) { if (accessOrder) // 添加的代码.如果是按照Lru算法实现,这重新调整该item在循环双向链表中的位置 makeTail((LinkedEntry<K, V>) e); return e.value; } } return null;}4.remove函数--同HashMap的remove函数// 覆写通知函数// 将该item从双向循环链表中删除@Override void postRemove(HashMapEntry<K, V> e) { LinkedEntry<K, V> le = (LinkedEntry<K, V>) e; le.prv.nxt = le.nxt; le.nxt.prv = le.prv; le.nxt = le.prv = null; // Help the GC (for performance)}
二.总结
1.要了解LinedHashMap的实现,要先知道他的父类HashMap的实现,LinkedHashMap的大部分实现都在他父类中实现2.当开启Lru算法的时候(accessOrder参数设置为true),LinkedHashMap比HashMap多的是该类自己维护双向循环链表,当增删改的时候会修改该链表,把最新的item放到末尾(Tail)3.本质:LinkedHashMap == HashMap + LinkedList
LruCache原理分析
1.实现
实现很简单,就相当于封装了LinkedHashMap(开启Lru算法),只是每次删除的时候检查当前数据大小是否超过阈值,如果超过则调用LinkedHashMap最老的元素(循环双向链表中维护的)
2.总结
我们的缓存容量是有限的,它会面临一个问题:当有新的内容需要加入我们的缓存,但我们的缓存空闲的空间不足以放进新的内容时,如何舍弃原有的部分内容从而腾出空间用来放新的内容。解决这个问题的算法有多种,比如LRU,LFU,FIFO等。需要注意区分的是LRU和LFU。前者是最近最少使用,即淘汰最长时间未使用的对象;后者是最近最不常使用,即淘汰一段时间内使用最少的对象。比如我们缓存对象的顺序是:A B C B D A C A ,当需要淘汰一个对象时,如果采用LRU算法,则淘汰的是B,因为它是最长时间未被使用的。如果采用LFU算法,则淘汰的是D,因为在这段时间内它只被使用了一次,是最不经常使用的。The LRU cache is a hash table of keys and double linked nodes. The hash table makes the time of get() to be O(1). The list of double linked nodes make the nodes adding/removal operations O(1).
参考文献
LRU Cache (Java)–principle
阅读全文
0 0
- LruCache 实现原理分析
- LruCache 实现原理分析
- LruCache原理分析
- LruCache原理分析整理
- Lrucache算法的原理简要分析
- Android LRUCache原理及源码分析(阿里巴巴)
- LruCache原理
- LruCache原理
- LruCache分析
- LruCache 分析
- 浅析LruCache原理
- LruCache实现原理
- Android LruCache技术原理
- 说说 LruCache 底层原理
- LRUCache的实现原理
- Android LruCache类分析
- Android LruCache使用分析
- Android缓存-LruCache分析
- 【libffi】动态调用&定义C函数
- A simple math problem
- 关于四次挥手的事儿
- 大话设计模式-Study-Tips-第三章-装饰模式
- jsp超强技能树
- LruCache原理分析
- chmod命令原理及用法详解
- 通俗解释 方差,标准差,协方差以及相关系数
- 格雷码
- 求二叉树中两个节点的最近公共祖先结点
- BZOJ1497 [NOI2006] 最大获利
- iw-3.15代码阅读
- Linux中zip压缩和unzip解压缩命令详解
- 八数码