• java实现LFU算法


    简介

    LFU(Least Frequently Used),即最不经常使用,淘汰一定时期内访问次数最少的元素,如果访问次数相同,则比较最新一次的访问时间。

    代码实现1

    import java.util.Comparator;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Map.Entry;
    
    public class LFUCache<K, V> {
    
      private int capacity;
      private Map<K, CacheObject<V>> cache;
    
      public LFUCache(int capacity) {
        this.capacity = capacity;
        cache = new HashMap<>(capacity);
      }
    
      public V get(K key) {
        CacheObject<V> cacheObject = cache.get(key);
        if (cacheObject == null) {
          return null;
        }
        return cacheObject.getValue();
      }
    
      public void put(K key, V value) {
        if (capacity == 0) {
          return;
        }
        CacheObject<V> cacheObject = cache.get(key);
        if (cacheObject == null) {
          if (cache.size() >= capacity) {
            //删除最少使用的键,使用次数相等,删除最久未使用的
            cache.entrySet().stream()
                .min(Comparator.comparing(Entry::getValue))
                .ifPresent(e -> {
                  cache.remove(e.getKey());
                });
          }
          cacheObject = new CacheObject<>(value);
        } else {
          cacheObject.setValue(value);
        }
        cache.put(key, cacheObject);
      }
    
      @Override
      public String toString() {
        return cache.toString();
      }
    
      static class CacheObject<V> implements Comparable<CacheObject<V>> {
    
        private V value;
        private long lastAccessTime;
        private int accessCount;
    
        CacheObject(V value) {
          setValue(value);
        }
    
        V getValue() {
          lastAccessTime = System.nanoTime();
          accessCount++;
          return value;
        }
    
        public void setValue(V value) {
          this.value = value;
          lastAccessTime = System.nanoTime();
          accessCount++;
        }
    
        @Override
        public String toString() {
          return value + ":" + accessCount;
        }
    
        @Override
        public int compareTo(CacheObject<V> o) {
          int res = Integer.compare(this.accessCount, o.accessCount);
          return res != 0 ? res : Long.compare(this.lastAccessTime, o.lastAccessTime);
        }
      }
    }
    

    存储被缓存对象的访问次数和最后访问时间,当缓存已经达到最大容量时,删除最少访问次数的数据,如果两个数据访问次数相等,删除最后访问时间久的数据。

    代码实现2

    import java.util.HashMap;
    import java.util.Map;
    import java.util.TreeSet;
    
    class LFUCache2<K, V> {
    
      private int capacity;
      private Map<K, CacheObject<K, V>> cache;
      private TreeSet<CacheObject<K, V>> treeSet;
    
      public LFUCache2(int capacity) {
        this.capacity = capacity;
        cache = new HashMap<>(capacity);
        treeSet = new TreeSet<>();
      }
    
      public V get(K key) {
        CacheObject<K, V> cacheObject = cache.get(key);
        if (cacheObject == null) {
          return null;
        }
        treeSet.remove(cacheObject);
        V value = cacheObject.getValue();
        treeSet.add(cacheObject);
        return value;
      }
    
      public void put(K key, V value) {
        if (capacity == 0) {
          return;
        }
        CacheObject<K, V> cacheObject = cache.get(key);
        if (cacheObject == null) {
          if (cache.size() >= capacity) {
            //删除最少使用的键,使用次数相等,删除最久未使用的
            cache.remove(treeSet.first().key);
            treeSet.pollFirst();
          }
          cacheObject = new CacheObject<>(key, value);
        } else {
          treeSet.remove(cacheObject);
          cacheObject.setValue(value);
        }
        treeSet.add(cacheObject);
        cache.put(key, cacheObject);
      }
    
      @Override
      public String toString() {
        return cache.toString();
      }
    
      static class CacheObject<K, V> implements Comparable<CacheObject<K, V>> {
    
        private K key;
        private V value;
        private long lastAccessTime;
        private int accessCount;
    
        CacheObject(K key, V value) {
          this.key = key;
          setValue(value);
        }
    
        V getValue() {
          lastAccessTime = System.nanoTime();
          accessCount++;
          return value;
        }
    
        public void setValue(V value) {
          this.value = value;
          lastAccessTime = System.nanoTime();
          accessCount++;
        }
    
        @Override
        public String toString() {
          return value + ":" + accessCount;
        }
    
        @Override
        public int compareTo(CacheObject<K, V> o) {
          int res = Integer.compare(this.accessCount, o.accessCount);
          return res != 0 ? res : Long.compare(lastAccessTime, o.lastAccessTime);
        }
      }
    }
    

    相比第一种,使用TreeSet存储访问次数的顺序关系,可以很快的得到最不经常使用的数据。

  • 相关阅读:
    mplayer命令行模式下的使用方法
    CentOS安装wireshark
    CentOS查看系统信息
    测试理论1
    单例模式
    接口测试
    rabbitmq
    redis数据库
    时间模块
    charles抓取数据
  • 原文地址:https://www.cnblogs.com/strongmore/p/14488134.html
Copyright © 2020-2023  润新知