巧记淘汰策略FIFO、LRU和LFU

什么是淘汰策略?

在容器容量一定的情况下,随着元素的慢慢增多,容量终有满的时刻。而淘汰策略是当容量要满的时候,用来淘汰剔除部分元素从而来腾出容器空间的策略。常用的淘汰策略有FIFO(先进先出)LRU(The Least Recently Used,最近最久未使用算法)LFU(Least Frequently Used ,最近最少使用算法)

FIFO

FIFO(先进先出)的思想是基于队列。如果一个数据是最先进入的,那么可以认为在将来它被访问的可能性很小。空间满的时候,最先进入的数据会被最早置换(淘汰)掉。

实现方式

使用双向链表,将新加的元素放到链表尾部,当元素满的时候,删除在队列首的元素。在java中LinkedHashMap继承了hashMap重写了newNodeafterNodeRemoval、的afterNodeInsertionafterNodeAccess。在LinkedHashMap维护了一个双向链表,在添加一个元素的时候,会将元素插入队列尾,这样我们在可以重写LinkedHashmapafterNodeInsertion方法实现FIFO的算法。

LRU

LRU(The Least Recently Used,最近最久未使用算法)的思想是基于时间,如果一个元素最久没有使用到,那么在将来中使用到的几率也最少,可以将最久未使用的元素从容器中剔除。

实现方式

LRU同样可以使用双向队列,每次访问某个元素的时候,将访问的元素移动到链表尾,此时链表头的元素便是最久没有访问到的元素,如果容量不够便可以移除表头元素。当把LinkedHashMap里的accessOrder=true的时候,每次访问map的元素会将元素放到内部维护的链表尾部,从而表头的元素便是最久没有使用到的元素。

LFU

LFU(Least Frequently Used ,最近最少使用算法)的思想是基于频率,如果一个元素的使用频率最少,那么在将来使用到的情况也最少,如果元素的频率使用相同,那么在比较其访问时间。

实现方式

LFU是根据次数和访问时间来决定置换元素的,所以我们可以使用:
HashMap<K, V>:来存储键值。
HashMap<K, C>:用另外一个Map来存储每个键的访问次数。
HashMap<K,LinkedHashSet<K>>:来存储如果两个元素访问次数一样的K。
在整个过程中,我们需要记录维护一个最小的访问次数min,当元素容量超出预期,需要置换元素出来的时候,可以从相同次数Map里面以min为K的所有K值,来判断是否将这些元素都淘汰,还是根据其他的因子(访问时间戳),来筛选出需要淘汰的元素。

猜你喜欢

转载自juejin.im/post/5da3d0f8f265da5b62534cdc