zoukankan      html  css  js  c++  java
  • 常见面试题之操作系统中的LRU缓存机制实现

    LRU缓存机制,全称Least Recently Used,字面意思就是最近最少使用,是一种缓存淘汰策略。换句话说,LRU机制就是认为最近使用的数据是有用的,很久没用过的数据是无用的,当内存满了就优先删除很久没有使用的数据

    基于LeetCode146,可以使用哈希链表或者自定义双端链表类+哈希表两种方法来实现LRU缓存机制。

    它应该支持以下操作:获取数据get和 写入数据put

    获取数据get(key):如果密钥 (key) 存在于缓存中,则获取密钥的值(总是正数),否则返回-1
    写入数据put(key, value):如果密钥不存在,则写入其数据值。当缓存容量达到上限时,它应该在写入新数据之前删除最近最少使用的数据值,从而为新的数据值留出空间。

    1. 基于LinkedHashMap实现LRU缓存机制

    class LRUCache {
        Map<Integer, Integer> map;
        int capacity;
        
        public LRUCache(int capacity) {
            this.capacity = capacity;
            map = new LinkedHashMap<>();
        }
        
        public int get(int key) {
            // 若key不存在返回-1
            if(!map.containsKey(key)) return -1;
            // 若key存在则获取key对应的val
            int val = map.get(key);
            // 更新位置
            put(key, val);
            return val;
        }
        
        public void put(int key, int val) {
            // 若缓存命中则先删除数据在重新放入以更新位置
            if(map.containsKey(key)) {
                map.remove(key);
                map.put(key, val);
            } else {
                // 若缓存未命中则先判断是否达到最大容量
                // 超出容量则删除最久没有使用的数据(利用迭代器删除第一个)
                if (capacity == map.size()) map.remove(map.keySet().iterator().next());
                // 删除完成后存放新数据
                map.put(key, val);
            }
        }
    }
    

    2. 基于DoubleList与HashMap实现LRU缓存机制

    如果不使用LinkedHashMap,可以自己造轮子,自定义DoubleList类并结合HashMap实现与LinkedHashMap相同的功能。

    class LRUCache {
        int capacity;
        DoubleList cache;
        Map<Integer, Node> map;
        
        public LRUCache(int capacity) {
            this.capacity = capacity;
            cache = new DoubleList();
            map = new HashMap<>();
        }
        
        public int get(int key) {
            if(!map.containsKey(key)) return -1;
            int val = map.get(key).val;
            put(key, val);
            return val;
        }
        
        public void put(int key, int val) {
            Node node = new Node(key, val);
            if(map.containsKey(key)) {
                cache.remove(map.get(key));
                cache.addFirst(node);
                map.put(key, node);
            } else {
                if(capacity == cache.size) map.remove(cache.removeLast().key);
                cache.addFirst(node);
                map.put(key, node);
            }
        }
    }
    
    class DoubleList {
        Node head, tail;
        int size;
        
        public DoubleList() {
            head = new Node(0, 0);
            tail = new Node(0, 0);
            head.next = tail;
            tail.prev = head;
            size = 0;
        }
        
        public void addFirst(Node node) {
            Node temp = head.next;
            node.next = temp;
            temp.prev = node;
            head.next = node;
            node.prev = head;
            size++;
        }
        
        public void remove(Node node) {
            Node temp = node.prev;
            temp.next = node.next;
            temp.next.prev = temp;
            size--;
        }
        
        public Node removeLast() {
            if (size == 0) return null;
            Node del = tail.prev;
            remove(del);
            return del;
        }
    }
    
    class Node {
        int key, val;
        Node prev, next;
        
        public Node(int key, int val) {
            this.key = key;
            this.val = val;
        }
    }
    
  • 相关阅读:
    一对多关系处理
    java中转换不同时区的时间
    maven
    学习设计模式
    算法
    mongodb学习总结
    mybatis源码分析(四) mybatis与spring事务管理分析
    学习数据库四大特性及事务隔离级别
    mybatis源码分析(三) mybatis-spring整合源码分析
    mybatis源码分析(二) 执行流程分析
  • 原文地址:https://www.cnblogs.com/chiaki/p/13551653.html
Copyright © 2011-2022 走看看