自定义实现缓存带上过期时间

想着实现缓存,只是提供下思路,还有很多的问题,无法进行应用

/**
 * 本质上是通过双链表 + 哈希表来实现的
 * 可以再加上过期时间,根据过期时间删除
 */
public class LRUCache {

    // 链表节点的定义
    class LRUNode{
        String key;
        Object value;
        LRUNode next;
        LRUNode pre;
        // 假设都是毫秒
        Long expireTime;

        public LRUNode(String key, Object value,Long expireTime) {
            this.key = key;
            this.value = value;
            this.expireTime = expireTime;
        }

        @Override
        public String toString() {
            return "LRUNode{" +
                    "key='" + key + '\'' +
                    ", value=" + value +
                    ", expireTime=" + expireTime +
                    '}';
        }
    }


    Map<String, LRUNode> map = new HashMap<>();
    LRUNode head;
    LRUNode tail;
    // 缓存最大容量,我们假设最大容量大于 1,
    // 当然,小于等于1的话需要多加一些判断另行处理
    int capacity;

    public LRUCache(int capacity) {
        this.capacity = capacity;
    }

    public void getAll(){
        System.out.println("输出所有map的值");
        for (String key : this.map.keySet()){
            System.out.println(key + "=============" + this.map.get(key).toString());
        }

        System.out.println("输出当前node的双向链表的值");
        LRUNode temp = head;
        while(true){
            if (temp == null){
                break;
            }
            System.out.println(temp.toString());
            temp = temp.next;
        }
    }

    public synchronized void put(String key, Object value, Long expireTime) {
        // 简化处理,如果头部没数据,那么直接加入进去
        if (head == null) {
            head = new LRUNode(key, value, expireTime);
            tail = head;
            map.put(key, head);
        }
        // 如果内部有数据,通过map去查询出数据
        LRUNode node = map.get(key);
        // 如果node为空,那么往后续去添加
        if (node != null) {
            // 更新值,直接更新值
            node.value = value;
            // 更新过期时间
            node.expireTime = expireTime == null ? null : (System.currentTimeMillis() + expireTime);
            // 把他从链表删除并且插入到头结点
            removeAndInsert(node);
        } else {
            LRUNode tmp = new LRUNode(key, value, expireTime);
            // 如果会溢出
            if (map.size() >= capacity) {
                // 如果溢出了,那么就先查询过期的key进行删除
                LRUNode tempDeleteNode = tail;
                for (;;){
                    if (tempDeleteNode == null){
                        // 如果指针全部循环完成后,还是没有过期的,那么进行一波最后的尾部删除
                        map.remove(tail.key);
                        tail = tail.pre;
                        tail.next = null;
                        break;
                    }
                    if (tempDeleteNode.expireTime != null && tempDeleteNode.expireTime <= System.currentTimeMillis()){
                        map.remove(tempDeleteNode.key);
                        // 删除当前的节点
                        tempDeleteNode.pre.next = tempDeleteNode.next;
                        // 保证gc回收
                        tempDeleteNode = null;
                        break;
                    }
                    tempDeleteNode = tempDeleteNode.pre;
                }
            }
            map.put(key, tmp);
            // 插入
            tmp.next = head;
            head.pre = tmp;
            head = tmp;
        }
    }

    public Object get(String key) {
        LRUNode node = map.get(key);
        if (node != null) {
            // 把这个节点删除并插入到头结点
            removeAndInsert(node);
            return node.value;
        }
        return null;
    }
    private synchronized void removeAndInsert(LRUNode node) {
        // 特殊情况先判断,例如该节点是头结点或是尾部节点
        if (node == head) {
            return;
        } else if (node == tail) {
            tail = node.pre;
            tail.next = null;
        } else {
            node.pre.next = node.next;
            node.next.pre = node.pre;
        }
        // 插入到头结点
        node.next = head;
        node.pre = null;
        head.pre = node;
        head = node;
    }


    public static void main(String[] args) {
        LRUCache lruCache = new LRUCache(4);
        lruCache.put("key1","xxxxx",null);
        lruCache.put("key2",1111,null);
        // 这个是删除过期时间的
//        lruCache.put("key3","yyyyy",2L);
        // 这个是删除最后一位的
        lruCache.put("key3","yyyyy",null);
        lruCache.put("key4","object",null);
        lruCache.getAll();
        System.out.println("=========================");

        lruCache.put("key5", "zzzz",null);
        lruCache.getAll();
    }
}

参考一个大佬的文章,现在暂时找不到。。。如果有人发现,评论贴一下

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值