方法一在leetcode上是可以通过的,在牛客通过不了,可以学习下。

方法一:利用LinkedHashMap



public class Solution extends LinkedHashMap<Integer, Integer>{
    
    private int capacity;
    
    public Solution(int capacity) {
        // accessOrder默认为false表示按插入顺序排序,为true表示按访问顺序排序
        // LRU自然是按访问顺序,所以让accessOrder=true
        super(capacity, 0.75F, true);
        this.capacity = capacity;
    }

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

    public void set(int key, int value) {
        super.put(key, value);
    }
    
    // removeEldestEntry字面意思移除年龄最大元素,默认返回false表示不移除
    // 我们重写这个方法,加一个判断条件,当 size > capacit 时移除
    @Override
    protected boolean removeEldestEntry(Map.Entry<Integer, Integer> eldest){
        return this.size() > capacity;
    }
}

关于 LinkedHashMap 具体使用大家可以阅读相应的源码

方法二:双链表+HashMap



public class Solution {
    class DLinkedNode<K, V> {
        private K key;
        private V value;
        DLinkedNode pre;
        DLinkedNode next;
        
        public DLinkedNode(){};
        
        public DLinkedNode(K key, V value){
            this.key = key;
            this.value = value;
        }
    }
    
    private int capacity;
    private Map<Integer, DLinkedNode> map = new HashMap<>();
    private DLinkedNode head;
    private DLinkedNode tail;
    private int size;
    
    public Solution(int capacity) {
         // write code here
        this.capacity = capacity;
        this.size = 0;
        this.head = new DLinkedNode();
        this.tail = new DLinkedNode();
        this.head.next = this.tail;
        this.tail.pre = this.head;
    }

    public int get(int key) {
         // write code here
        DLinkedNode<Integer, Integer> node = map.get(key);
        if(node == null){
            return -1;
        }
        moveToHead(node);
        return node.value;
    }

    public void set(int key, int value) {
         // write code here
        DLinkedNode<Integer, Integer> node = map.get(key);
        if(node == null){
            DLinkedNode<Integer, Integer> newNode = new DLinkedNode<>(key,value);
            map.put(key, newNode);
            addToHead(newNode);
            size++;
            if(size > this.capacity){
                DLinkedNode tail = removeTail();
                map.remove(tail.key);
                size--;
            }
        }else{
            node.value = value;
            moveToHead(node);
        }
    }
    
    // 插入
    public void addToHead(DLinkedNode node){
        node.next = this.head.next;
        node.next.pre = node;
        node.pre = this.head;
        this.head.next = node;
        
    }
        
    // 删除
    public DLinkedNode removeTail(){
        DLinkedNode p = this.tail.pre;
        this.tail.pre.pre.next = this.tail;
        this.tail.pre = this.tail.pre.pre;
        return p;
    }
    
    // 将该结点移到头部
    // 因为map中存放的是结点的索引(地址),所以我们不需要遍历链表去定位到这个node,可以直接用这个地址定位到这个node
    public void moveToHead(DLinkedNode node){
        // 把node从原位置摘除
        node.next.pre = node.pre;
        node.pre.next = node.next;
        // 将node移到表头
        node.next = head.next;
        node.next.pre = node;
        node.pre = head;
        head.next = node;
    }
}