实现LRU缓存

简介: 实现LRU缓存

正文


package com.breakpoint.lru;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
 * @author 赵立刚 <zlgtop@163.com>
 * Created on 2021-03-08
 */
public class LruCacheTest {
    public static void main(String[] args) {
        LruCache<String, String> lruCache = new LruCache<>(3);
        lruCache.put("1", "1");
        lruCache.put("2", "2");
        lruCache.put("3", "3");
        lruCache.put("4", "4");
        String value = lruCache.getValue("1");
        System.out.println(1);
    }
    public static final class LruCache<K, V> {
        private final Map<K, Node<K, V>> map = new ConcurrentHashMap<>();
        private final Node<K, V> head;
        private final Node<K, V> tail;
        private final int maxSize;
        public LruCache(int maxSize) {
            this.maxSize = maxSize;
            head = new Node<K, V>(null, null);
            tail = new Node<K, V>(null, null);
            head.next = tail;
            tail.pre = head;
        }
        public void put(K key, V value) {
            Node<K, V> kvNode = map.get(key);
            if (null == kvNode) {
                if (maxSize < map.size() + 1) {
                    // 超过了最大的空间
                    Node<K, V> tail = this.tail.pre;
                    this.tail.pre = tail.pre;
                    tail.pre.next=this.tail;
                    map.remove(tail.key);
                }
                Node<K, V> cur = new Node<>(key, value);
                map.put(key, cur);
                head.next.pre = cur;
                cur.next = head.next;
                head.next = cur;
                cur.pre = head;
            } else {
                // 提前
                Node<K, V> pre = kvNode.pre;
                pre.next = kvNode.next;
                kvNode.next.pre = pre;
                // 插入开始位置
                head.next.pre = kvNode;
                kvNode.next = head.next;
                head.next = kvNode;
                kvNode.pre = head;
                // 更新对象
                kvNode.value = value;
            }
        }
        public V getValue(K key) {
            Node<K, V> kvNode = map.get(key);
            if (null != kvNode) {
                // 提前
                Node<K, V> pre = kvNode.pre;
                pre.next = kvNode.next;
                kvNode.next.pre = pre;
                // 插入开始位置
                head.next.pre = kvNode;
                kvNode.next = head.next;
                head.next = kvNode;
                kvNode.pre = head;
                return kvNode.value;
            }
            return null;
        }
        private final class Node<T, V> {
            private T key;
            private V value;
            private Node<K, V> pre;
            private Node<K, V> next;
            public Node(T key, V value) {
                this.key = key;
                this.value = value;
            }
        }
    }
}

时间复杂度O(1)

相关文章
|
5天前
|
缓存 算法
LRU(Least Recently Used)算法是一种常用的计算机缓存替换算法
LRU算法是基于页面使用频率的缓存策略,优先淘汰最近最久未使用的页面。实现可采用双向链表或数组,前者灵活,后者时间复杂度低。优点是利用时间局部性提高命中率,简单易实现;缺点是占用空间,对循环访问和随机访问场景适应性不佳。
22 0
|
11天前
|
存储 缓存 算法
面试遇到算法题:实现LRU缓存
V哥的这个实现的关键在于维护一个双向链表,它可以帮助我们快速地访问、更新和删除最近最少使用的节点,同时使用哈希表来提供快速的查找能力。这样,我们就可以在 O(1) 的时间复杂度内完成所有的缓存操作。哈哈干净利索,回答完毕。
|
28天前
|
存储 缓存 Java
java如何实现一个LRU(最近最少使用)缓存?
实现了一个LRU缓存,使用双向链表保持访问顺序,哈希表用于定位元素。Java代码中,`LRUCache`类包含容量、哈希表及链表头尾节点。`get`方法查哈希表,找到则移动至链表头并返回值,否则返回-1。`put`方法更新或插入节点,超出容量则移除最不常用节点。
16 6
|
1月前
|
缓存 算法 Java
如何实现缓存与LRU算法以及惰性过期
如何实现缓存与LRU算法以及惰性过期
32 1
|
2月前
|
存储 缓存 算法
深入探究LRU缓存机制:优化内存利用与提升性能
深入探究LRU缓存机制:优化内存利用与提升性能
197 1
|
2月前
|
缓存
LRU 缓存置换策略:提升系统效率的秘密武器(下)
LRU 缓存置换策略:提升系统效率的秘密武器(下)
|
2月前
|
存储 缓存 算法
LRU 缓存置换策略:提升系统效率的秘密武器(上)
LRU 缓存置换策略:提升系统效率的秘密武器(上)
|
3月前
|
缓存 监控 安全
如何使用LRU缓存来提高程序的性能?
如何使用LRU缓存来提高程序的性能?
21 3
|
4月前
|
Shell Unix Linux
Linux 终端命令之文件浏览(3) less
Linux 终端命令之文件浏览(3) less
32 0
Linux 终端命令之文件浏览(3) less
|
4月前
|
Java Go C++
Java每日一练(20230427) 螺旋矩阵、LRU缓存机制、解数独
Java每日一练(20230427) 螺旋矩阵、LRU缓存机制、解数独
27 0
Java每日一练(20230427) 螺旋矩阵、LRU缓存机制、解数独