LRU Cache 设计与实现

原创 2015年07月08日 13:22:33

LRU 指的是 Least Recently Used 的缩写,即最近最少使用算法。是操作系统中常用的一种页面替换算法,在系统发生缺页中断时,置换未使用时间最长的页面。也常常用在 Cache 中,缓存最近使用过的数据。

数据结构

高效的实现 LRU 算法一般是使用哈希表 + 双链表,其中双链表用于缓存数据节点,并且其中的结点是按照最近被使用的时间排序的,每当一个数据节点被使用时或者一个新的数据节点加入时,需要将其放至表头位置。并且,当 Cache 已经满了时,此时如果一个新的数据结点加入到链表中时,需要替换掉最近最久使用的表尾位置的数据节点。

哈希表的作用是为了可以达到迅速找到某个结点,在没有哈希表的情况下,需要从链表中逐个遍历比较,时间复杂度为 O(n),在使用哈希表的情况下,可以使得我们可以在 O(1) 的时间找到需要访问的结点,或者返回未找到。

接口

Cache 的主要接口有

LRUCache(int capacity)
int get(int key)
void put(int key, int value)

LRU Cache 的主要接口有 构造函数 LRUCache 用于初始化一个容量为capacity 的缓存。get 用于从缓存中读出数据,并且需要将其放置开头位置,当缓存中没有所需的数据时,返回特殊值 -1。put 用于在缓存中加入一个新的数据。当加入一个新数据时,需要先检查缓存中是否已经存在与插入数据键值相同的数据以及容量是否已经满了。当缓存已存在键值相同的数据时,可以将其取出,修改节点的值,将其放置链表的开头并将其重新加入哈希表中。若缓存中不存在键值相同的数据时,先检查容量是否已满,在缓存容量已满的情况下,需要先去掉链表尾结点。并重新根据键值和数据生成一个新的结点放到链表的开头位置并加入哈希表中。

代码实现

完整的 Java 实现代码如下:

import java.util.*;

/**
 * 用带头节点和尾节点的双链表 + 哈希表 实现 LRU 缓存
 * Created by iprocoder on 15-5-24.
 */
public class LRUCache {

    /**
     * 缓存节点
     */
    private class CacheNode {

        int key;
        int value;
        CacheNode prev;
        CacheNode next;

        public CacheNode(int key, int value) {
            this.key = key;
            this.value = value;
        }

        public CacheNode() {
        }
    }

    private int capacity;
    private int num;
    private Map<Integer, CacheNode> map;
    private CacheNode head;
    private CacheNode tail;

    public LRUCache(int capacity) {
        this.capacity = capacity;
        this.num = 0;
        this.map = new HashMap<>(capacity);
        this.head = new CacheNode();
        this.tail = new CacheNode();
        this.head.prev = null;
        this.head.next = tail;
        this.tail.prev = head;
        this.tail.next = null;
    }

    public int get(int key) {
        CacheNode cacheNode = map.get(key);

        if (cacheNode == null)
            return -1;
        detach(cacheNode);
        attach(cacheNode);
        return cacheNode.value;
    }

    public void set(int key, int value) {
        CacheNode cacheNode = map.get(key);
        if (cacheNode != null) {
            detach(cacheNode);
            cacheNode.value = value;
            attach(cacheNode);
        } else {
            if (num == capacity) {
                cacheNode = tail.prev;
                detach(cacheNode);
                map.remove(cacheNode.key);
            } else {
                num++;
                cacheNode = new CacheNode();
            }
            cacheNode.key = key;
            cacheNode.value = value;
            map.put(key, cacheNode);
            attach(cacheNode);
        }
    }

    /**
     * 分离节点
     * @param cacheNode
     */
    private void detach(CacheNode cacheNode) {
        cacheNode.prev.next = cacheNode.next;
        cacheNode.next.prev = cacheNode.prev;
    }

    /**
     * 将节点插入头部
     * @param cacheNode
     */
    private void attach(CacheNode cacheNode) {
        cacheNode.prev = head;
        cacheNode.next = head.next;
        head.next = cacheNode;
        cacheNode.next.prev = cacheNode;
    }

    public static void main(String[] args) {
        LRUCache lruCache = new LRUCache(1);
        lruCache.set(1, 3);
        System.out.println(lruCache.get(1));
        lruCache.set(3, 2);
        System.out.println(lruCache.get(2));
        System.out.println(lruCache.get(1));
    }
}

参考链接

http://www.hawstein.com/posts/lru-cache-impl.html

Written with StackEdit.

设计并实现一个LRU Cache

一、什么是Cache1 概念Cache,即高速缓存,是介于CPU和内存之间的高速小容量存储器。在金字塔式存储体系中它位于自顶向下的第二层,仅次于CPU寄存器。其容量远小于内存,但速度却可以接近CPU的...

设计并实现一个LRU Cache (java)

什么是Cache 概念 Cache,即高速缓存,是介于CPU和内存之间的高速小容量存储器。在金字塔式存储体系中它位于自顶向下的第二层,仅次于CPU寄存器。其容量远小于内存,但速度却可以接近CPU的频率...

如何设计实现一个LRU Cache?

1. 什么是LRU Cache?在LeetCode上看到一个LRU Cache实现的题目,题目描述是这样的: Design and implement a data structure for L...

LRU Cache 设计与实现

LRU Cache 设计与实现LRU 是 Least Recently Used 的缩写,即最近最少使用算法。是操作系统中常用的一种页面替换算法,在系统发生缺页中断时,置换未使用时间最长的页面。也常常...

Cache的设计和实现 LRU Cache

Cache的应用非常广泛,其实Cache是一种思想,一个广义的词汇,一种在性能和金钱的权衡上的思想。 Cache的思想用在很多地方,使用的载体也不同,都是位于相对高速设备和相对低速设备之间,起到...

Cache的设计和实现 LRU Cache

Cache的设计和实现 LRU Cache Cache的应用非常广泛,其实Cache是一种思想,一个广义的词汇,一种在性能和金钱的权衡上的思想。 Cache的思想用在很多地方,使用的载...

【Leetcode】:LRU Cache_缓存淘汰算法LRU的设计与实现

内存淘汰算法是一个比较重要的算法,经常会被问道:如果让你设计一个LRU算法你会怎么做?尽可能的保持存取的高效。那么就依着这道算法题对LRU进行一个简单的介绍。...

如何设计一个LRU Cache?

如何设计一个LRU Cache? Google和百度的面试题都出现了设计一个Cache的题目,什么是Cache,如何设计简单的Cache,通过搜集资料,本文给出个总结。  通常的问题描述可...

如何设计一个LRU Cache

如何设计一个LRU Cache? Google和百度的面试题都出现了设计一个Cache的题目,什么是Cache,如何设计简单的Cache,通过搜集资料,本文给出个总结。 通常的问题描述可以是这样:...

如何设计一个LRU Cache?

如何设计一个LRU Cache? Google和百度的面试题都出现了设计一个Cache的题目,什么是Cache,如何设计简单的Cache,通过搜集资料,本文给出个总结。  通常的问题描述可以是这样...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:LRU Cache 设计与实现
举报原因:
原因补充:

(最多只允许输入30个字)