LRU缓存

这是一个很经典的面试题

146. LRU 缓存 - 力扣(LeetCode)

请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。

实现 LRUCache 类:

  • LRUCache(int capacity)正整数 作为容量 capacity 初始化 LRU 缓存
  • int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1
  • void put(int key, int value) 如果关键字 key 已经存在,则变更其数据值 value ;如果不存在,则向缓存中插入该组 key-value 。如果插入操作导致关键字数量超过 capacity ,则应该 逐出 最久未使用的关键字。

函数 getput 必须以 O(1) 的平均时间复杂度运行。

这是一个设计数据结构的题

如果没有第三个要求,HashMap+List就可以是实现,

可是还需要O(1)的复杂度

可以使用双向链表加Hash表去解决,为什么要用hash表了,因为要快速判断这个key存在于这个链表,

解法一:自定义双向链表

java 复制代码
class LRUCache3{
    private static class Node{
        int key,value;
        Node pre,next;
        public Node(int key,int value){
            this.key=key;
            this.value=value;
        }
    }
    private int capacity;
    private Node head=new Node(0,0);
    private HashMap<Integer,Node> map=new HashMap<>();

    public LRUCache3(int capacity) {
        this.capacity=capacity;
        head.pre=head;
        head.next=head;
    }
    public int get(int key){
         if(!map.containsKey(key)){
             return -1;
         }
         Node k=map.get(key);
         remove(k);
         add(k);
         return k.value;
    }
    public void put(int key,int value){
             if(map.containsKey(key)){
                 Node node = map.get(key);
                 node.value=value;
                 remove(node);
                 add(node);
                 return ;
             }
             if(map.size()==capacity){
                 Node last = head.pre;
                 remove(last);
                 map.remove(last.key);
             }
             add(new Node(key,value));
    }
    private void remove(Node k){
     k.pre.next=k.next;
     k.next.pre=k.pre;
    }
    private void add(Node k){
        k.pre=head;
        k.next=head.next;
        k.pre.next=k;
        k.next.pre=k;
    }
}

解法二:使用LinkedHashmap 本身自带双向链表

LinkedHashMap

java 复制代码
LinkedHashMap<Integer,String> linkedHashMap = new LinkedHashMap<>(16,0.75f,true);

boolean accessOrder决定按什么排序,为true则为按访问顺序,为false则为插入顺序

java 复制代码
    public LinkedHashMap(int initialCapacity,
                         float loadFactor,
                         boolean accessOrder) {
        super(initialCapacity, loadFactor);
        this.accessOrder = accessOrder;
    }

如果按照插入顺序写会固定不变,所以应该用true

java 复制代码
class  LRUCache2{
    // LinkedHashMap 最早是在上面, 最近使用的在下面。
    private int capacity;
    private LinkedHashMap<Integer, Integer> map;
    public LRUCache2(int capacity) {
        this.capacity = capacity;
        map = new LinkedHashMap<>();
    }

    public int get(int key) {
        Integer remove = map.remove(key);
        if(remove !=null ){
            map.put(key,remove);
            return remove;
        }
        return -1;
    }

    public void put(int key, int value) {
         if(map.remove(key)!=null){
             map.put(key,value);
             return ;
         }
         if(map.size()==capacity){
             map.remove(map.keySet().iterator().next());
         }
         map.put(key,value);
    }
}

第三种 继承LinkedHashMap

java 复制代码
class  LRUCache extends LinkedHashMap<Integer, Integer>{
    private static final float DEFAULT_LOAD_FACTOR = 0.75f;
    private final int capacity;
    public LRUCache(int capacity) {
        super(capacity, DEFAULT_LOAD_FACTOR, true);
        this.capacity = capacity;
    }

    @Override
    protected boolean removeEldestEntry(Map.Entry<Integer, Integer> eldest) {
        return size() > capacity;
    }

    public int get(int key) {
      return super.getOrDefault(key, -1);
    }

}
相关推荐
只是有点小怂4 分钟前
受害者缓存(Victim Cache)
缓存
刘艳兵的学习博客2 小时前
刘艳兵-DBA033-如下那种应用场景符合Oracle ROWID存储规则?
服务器·数据库·oracle·面试·刘艳兵
simpleGq2 小时前
Redis知识点整理 - 脑图
数据库·redis·缓存
运维小文3 小时前
服务器硬件介绍
运维·服务器·计算机网络·缓存·硬件架构
日里安3 小时前
8. 基于 Redis 实现限流
数据库·redis·缓存
jerry60910 小时前
7天用Go从零实现分布式缓存GeeCache(改进)(未完待续)
分布式·缓存·golang
吾店云建站10 小时前
WordPress 6.7 “Rollins”发布
科技·程序人生·职场和发展·创业创新·程序员创富
用户31574760813513 小时前
成为程序员的必经之路” Git “,你学会了吗?
面试·github·全栈
看山还是山,看水还是。13 小时前
Redis 配置
运维·数据库·redis·安全·缓存·测试覆盖率
谷新龙00113 小时前
Redis运行时的10大重要指标
数据库·redis·缓存