当前位置:   article > 正文

LRU、LFU_lfu、lru

lfu、lru

LRU,即:最近最少使用淘汰算法(Least Recently Used)。LRU是淘汰最长时间没有被使用的数据。
LFU,即:最不经常使用淘汰算法(Least Frequently Used)。LFU是淘汰一段时间内,使用次数最少的数据。

举例:    
数据2  1  2  1  2  3  4,加入4时内存超过阈值。
根据LRU会淘汰1,因为1距离想加入4的时间点(也就是淘汰时间点)最长。
根据LFU会淘汰3,因为加入4前的这段时间里,3的使用次数最少。

LRU算法实现:

LeetCode官方题解:https://leetcode-cn.com/problems/lru-cache/solution/lruhuan-cun-ji-zhi-by-leetcode-solution/

这里记录一下借助LinedHashMap的原有机制实现。

  1. class LRUCache extends LinkedHashMap<Integer,Integer>{
  2. private int capacity;
  3. public LRUCache(int capacity) {
  4. // LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder)
  5. super(capacity, 0.75F, true);
  6. this.capacity = capacity;
  7. }
  8. public int get(int key) {
  9. return super.getOrDefault(key,-1);
  10. }
  11. public void put(int key, int value) {
  12. super.put(key,value);
  13. }
  14. protected boolean removeEldestEntry(Map.Entry<Integer,Integer> eldest){
  15. return size() > capacity;
  16. }
  17. }

LinkedHashMap的底层数据结构和HashMap一样,采用数组+单向链表(JDK1.8之前),只是在节点Entry中增加了before和after变量,用于维护一个双向链表来保存LinkedHashMap的节点顺序。

当accessOrder为false时(默认情况),LinkedHashMap的节点顺序是插入顺序。而accessOrder为true之后,在访问结点时,会将相应结点移动到双向链表的尾部,所以头部的节点是最近最少使用的节点,节点都是唯一的,所以头部的节点其实也是最近未使用的节点。

LinkedHashMap:

  1. public V get(Object key) {
  2. Node<K,V> e;
  3. if ((e = getNode(hash(key), key)) == null)
  4. return null;
  5. if (accessOrder)
  6. afterNodeAccess(e);
  7. return e.value;
  8. }

put到removeEldestEntry的调用路径:

HashMap:

  1. public V put(K key, V value) {
  2. return putVal(hash(key), key, value, false, true);
  3. }
  1. final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
  2. boolean evict) {
  3. Node<K,V>[] tab; Node<K,V> p; int n, i;
  4. if ((tab = table) == null || (n = tab.length) == 0)
  5. n = (tab = resize()).length;
  6. if ((p = tab[i = (n - 1) & hash]) == null)
  7. tab[i] = newNode(hash, key, value, null);
  8. else {
  9. Node<K,V> e; K k;
  10. if (p.hash == hash &&
  11. ((k = p.key) == key || (key != null && key.equals(k))))
  12. e = p;
  13. else if (p instanceof TreeNode)
  14. e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
  15. else {
  16. for (int binCount = 0; ; ++binCount) {
  17. if ((e = p.next) == null) {
  18. p.next = newNode(hash, key, value, null);
  19. if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
  20. treeifyBin(tab, hash);
  21. break;
  22. }
  23. if (e.hash == hash &&
  24. ((k = e.key) == key || (key != null && key.equals(k))))
  25. break;
  26. p = e;
  27. }
  28. }
  29. if (e != null) { // existing mapping for key
  30. V oldValue = e.value;
  31. if (!onlyIfAbsent || oldValue == null)
  32. e.value = value;
  33. afterNodeAccess(e);
  34. return oldValue;
  35. }
  36. }
  37. ++modCount;
  38. if (++size > threshold)
  39. resize();
  40. afterNodeInsertion(evict);
  41. return null;
  42. }

LinkedHashMap:

  1. void afterNodeInsertion(boolean evict) { // possibly remove eldest
  2. LinkedHashMap.Entry<K,V> first;
  3. if (evict && (first = head) != null && removeEldestEntry(first)) {
  4. K key = first.key;
  5. removeNode(hash(key), key, null, false, true);
  6. }
  7. }
  1. protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {
  2. return false;
  3. }

顺便说一下插入和访问时的节点顺序维护:

LinkedHashMap:

  1. void afterNodeAccess(Node<K,V> e) { // move node to last
  2. LinkedHashMap.Entry<K,V> last;
  3. if (accessOrder && (last = tail) != e) {
  4. LinkedHashMap.Entry<K,V> p =
  5. (LinkedHashMap.Entry<K,V>)e, b = p.before, a = p.after;
  6. p.after = null;
  7. if (b == null)
  8. head = a;
  9. else
  10. b.after = a;
  11. if (a != null)
  12. a.before = b;
  13. else
  14. last = b;
  15. if (last == null)
  16. head = p;
  17. else {
  18. p.before = last;
  19. last.after = p;
  20. }
  21. tail = p;
  22. ++modCount;
  23. }
  24. }

LFU:

简单暴力的解法是记录各节点访问频次,淘汰节点时选择频次最小的节点即可。高级的LeetCode官方题解看链接:平衡二叉树或者双哈希表https://leetcode-cn.com/problems/lfu-cache/solution/lfuhuan-cun-by-leetcode-solution/

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/寸_铁/article/detail/950791
推荐阅读
相关标签
  

闽ICP备14008679号