Java算法系列5 — 用队列和哈希表实现LRU缓存方案

LRU:Least Recently Used 最近最少使用。常用于缓存淘汰策略、页面置换的一种算法。

如何实现LRU?
使用双向链表实现的队列和一个哈希表可以实现,队列的最大容量为缓存的大小,哈希表中页号作为键,缓存在队列中的结点地址作为值。

具体代码实现:

import java.util.ArrayDeque;
import java.util.HashSet;

/**
 * 用队列和哈希表实现LRU缓存方案
 */
public class LRU {

    private int cacheSize;

    private ArrayDeque<Integer> queue = new ArrayDeque<Integer>();

    private HashSet<Integer> hashSet = new HashSet<Integer>();

    public LRU(int cacheSize){
        this.cacheSize = cacheSize;
    }

    //判断缓存队列是否已满
    private boolean isQueueFull(){
        return queue.size() == cacheSize;
    }

    //把页号为pageNum的也缓存到队列中,同时也添加到Hash表中
    private void enQueue(int pageNum){
        //如果队列满了,需要删除队尾的缓存页
        if(isQueueFull()){
            hashSet.remove(queue.getLast());
            queue.pollLast();
        }
        queue.addFirst(pageNum);
        //把新缓存的结点同时添加到hash表中
        hashSet.add(pageNum);
    }

    /**
     * 当访问某一个page的时候会调用这个函数,对于访问的page 有两种情况:
     * 1、如果Page在缓存队列中,直接把这个结点移动到队首
     * 2、如果page不在这个缓存队列中,把这个page缓存到队首
     */
    public void accessPage(int pageNum){
        //page不在缓存队列中
        if(!hashSet.contains(pageNum)){
            enQueue(pageNum);
        }
        //page已经在缓存队列中
        else if(pageNum != queue.getFirst()){
            queue.remove(pageNum);
            queue.addFirst(pageNum);
        }
    }

    //打印
    public void printQueue(){
        while(!queue.isEmpty()){
            System.out.print(queue.pop()+" ");
        }
    }
	//测试
    public static void main(String[] args) {
        LRU lru = new LRU(5);
        //访问
        lru.accessPage(1);
        lru.accessPage(3);
        lru.accessPage(5);
        lru.accessPage(1);
        lru.accessPage(4);
        lru.accessPage(6);
        lru.accessPage(2);

        lru.printQueue();

    }
}
测试结果:2 6 4 1 5 

你可能感兴趣的:(java)