LRU最近最少使用的Java实现

1LRULeastRecently Used的缩写,即最近最少使用,常用于页面置换算法,是为虚拟页式存储管理服务的。

2:为了实现LRU,需要做到

    查询出最近最晚使用的项

    给最近使用的项做一个标记

链表可以实现这个两个操作,标记最近使用的项只需要将使用的项从当前位置删除,并将该项放到头部。那么最近最少使用的项就在链表尾部。比较困难的是怎样快速的在链表中找到该项。查询的话可以借助hash表,哈希表可以在常量时间内索引某个对象。如果建立一个key到链表节点的哈希表就可以在常量时间内找到最近使用的节点。也能在常量时间内判断节点是否存在。这种形式的数据结构在java中是有的:LinkedHashMap

3LinkedHashMap

    LinkedHashMap自身已经实现了顺序存储,默认情况下是按照元素的添加顺序存储,也可以启用按照访问顺序存储,即最近读取的数据放在最前面,最早读取的数据放在最后面,然后它还有一个判断是否删除最老数据的方法,默认是返回false,即不删除数据,我们使用LinkedHashMap实现LRU缓存的方法就是对LinkedHashMap实现简单的扩展,扩展方式有两种,一种是inheritance,一种是delegation,具体使用什么方式看个人喜好。

import java.util.LinkedHashMap;
import java.util.Map;
//参考:https://www.cnblogs.com/ProtectedDream/p/6932478.html
//此实现为非线程安全,若在多线程环境下使用需要在相关方法上添加synchronized以实现线程安全操作
public class LruCache1 extends LinkedHashMap {
    private final int MAX_CACHE_SIZE;

//    ceil 天花板
    public LruCache1(int cacheSize) {
        super((int) Math.ceil(cacheSize / 0.75) + 1, 0.75f, true);
        MAX_CACHE_SIZE = cacheSize;
    }

//    默认返回false, 在程序中效果就是不删除最近最少使用的值
    protected boolean removeEldestEntry(Map.Entry eldest) {
        return size() > MAX_CACHE_SIZE;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        for (Map.Entry entry : entrySet()) {
            sb.append(String.format("%s:%s ", entry.getKey(), entry.getValue()));
        }
        return sb.toString();
    }

//    public static void main(String[] args) {
//        LruCache1 cache = new LruCache1(3);
//        for (int i = 0; i < 3; i++) {
//            cache.put(i, i);
//        }
//        System.out.println(cache);
//        cache.put(4, 4);
//        System.out.println(cache);
//        cache.get(2);
//        System.out.println(cache);
//
//        for (Map.Entry entry : cache.entrySet()) {
//            System.out.println(entry.getValue());
//        }
//    }
}

自己写了一个用链表实现的LRU,当然,其中的问题就是查找的时间复杂度是O(n),具体见github

https://github.com/ivalue2333/Javacore/tree/master/src/main/java/service/lru/MyLinkedList

你可能感兴趣的:(Java)