LRU(Least Recently Used)即最近最少使用,是一种缓存算法(页面置换算法)。咱们知道,缓存一般是具备固定大小的,他应该只保存那些经常被用到的数据,而数据如何更新则是经过缓存算法实现,LRU算法就是一种简单,经常使用的缓存算法。node
LRU算法是核心思想是:若是一个数据在最近一段时间都没有被用到,那么它在未来被使用到的可能性也很小。故当缓存空间已满的状况下,咱们须要淘汰掉最久没有被访问到的数据。理想的LRU算法读写是时间复杂度应该都为O(1)。算法
为了达到理想的性能,咱们须要一种既能够按访问顺序排序,又能够在常数时间随机访问的数据结构。这里能够采用HashMap和双向链表实现。HashMap能够存储Key,能够在常数时间里读写Key,而Value用来指向双向链表的节点,为了在常数时间里移除一个节点咱们还须要Head节点和Tril节点。缓存
代码实现以下:数据结构
class LruCache<K, V>() { private data class Node<K, V>( var key: K? = null, var value: V? = null, var prev: Node<K, V>? = null, var next: Node<K, V>? = null ) private val hashMap: HashMap<K, Node<K, V>> = hashMapOf() private var count = 0 private var capacity = 8 private val head: Node<K, V> = Node() private val tail: Node<K, V> = Node() init { head.next = tail tail.prev = head } constructor(capacity: Int) : this() { this.capacity = capacity } fun get(key: K): V? { val node = hashMap[key] ?: return null move(node) return node.value } fun put(key: K, value: V) { val node = hashMap[key] if (node == null) { val newNode = Node(key, value) add(newNode) hashMap[key] = newNode ++count if (count > capacity) { val deleteNode = delete() hashMap.remove(deleteNode.key) --count } } else { node.value = value move(node) } } private fun add(node: Node<K, V>) { node.prev = head node.next = head.next head.next!!.prev = node head.next = node } private fun remove(node: Node<K, V>) { val prev = node.prev!! val next = node.next!! prev.next = next next.prev = prev } private fun move(node: Node<K, V>) { remove(node) add(node) } private fun delete(): Node<K, V> { val node = tail.prev!! remove(node) return node } }
而在实际使用中,咱们可使用LinkedHashMap实现,其内部就是使用双向链表,咱们只需稍做修改便能使用。
在LinkedHashMap的构造参数(initialCapacity:Int, loadFactor:Float,accessOrder:Boolean)
中,initialCapacity
是HashMap的初始大小,loadFactor
则是装载因子,accessOrder=false
表示基于插入顺序,accessOrder=true
表示基于访问顺序。
实现LRU的关键方法:ide
override fun removeEldestEntry(eldest: MutableMap.MutableEntry<K, V>?): Boolean { return size > capacity }
以上表示当LinkedHashMap大小超过咱们设定的大小时,移除链表首部的节点性能
class LruChche<K, V>(private val capacity: Int = 8) { private var hashMap: LinkedHashMap<K, V> = object : LinkedHashMap<K, V> (capacity / 0.75.toInt() + 1, 0.75f, true) { override fun removeEldestEntry(eldest: MutableMap.MutableEntry<K, V>?): Boolean { return size > capacity } } fun get(key: K): V? = hashMap[key] fun put(key: K, value: V) { hashMap[key] = value } }
第一次据说LRU算法是在现代操做系统这本书中,但引发我深究的是Glide这个库在自定义Model的时候,便有了一探究竟的想法,故整理资料写下这些文字,一面是为了加深本身的影响,另外一面也但愿我所说的能让你们更简单的去理解LRU,一块儿学习。学习