使用单链表实现最基本的LRU

import java.util.Random;

/**
 * 自己实现LRU
 */
public class MyLRUImpl<K, V> {

    private int cap;

    private int size = 0;

    private Node<K, V> head;

    private Node<K, V> tail;

    private DB<K, V> db;

    /**
     * 设定容量,以及访问数据库的抽象工厂
     * @param cap
     * @param db
     */
    public MyLRUImpl(int cap, DB<K, V> db) {
        this.cap = cap;
        this.db = db;
    }

    public V get(K key) {
        if (key == null) {
            throw new NullPointerException();
        }
        Node<K, V> temp = head;
        Node<K, V> ahead = null;
        while (temp != null) {
            if (temp.key.equals(key)) {
                if (temp.next != null) {
                    System.out.println("找到了匹配的缓存");
                    moveToTail(ahead, temp);
                }
                return temp.value;
            }
            ahead = temp;
            temp = temp.next;
        }

        V newValue = getFromDB(key);
        Node<K, V> newNode = new Node<>(key, newValue);

        if (head == null) {
            head = newNode;
            tail = newNode;
        }

        tail.next = newNode;
        tail = newNode;
        size++;
        checkCap();
        return newValue;
    }

    private V getFromDB(K key) {
        return db.getFromDB(key);
    }

    private void moveToTail(Node<K, V> ahead, Node<K, V> target) {

        if (target == tail) {
            return;
        }

        if (head == target) {
            head = target.next;
            tail.next = target;
            tail = target;
        } else {
            ahead.next = target.next;
            tail.next = target;
            tail = target;
        }
        target.next = null;


    }

    public V put(K key, V value) {
        if (key == null) {
            throw new NullPointerException();
        }

        if (head == null) {
            tail = head = new Node<>(key, value);
            size++;
            return null;
        }

        Node<K, V> temp = head;
        while (temp != null) {
            if (temp.key.equals(key)) {
                V oldValue = temp.value;
                temp.value = value;
                System.out.println("进行了替换");
                return oldValue;
            }
            temp = temp.next;
        }

        temp = new Node<>(key, value);
        tail.next = temp;
        tail = temp;
        size++;

        checkCap();

        return null;

    }

    private void checkCap() {
        if (size > cap) {
            System.out.println("淘汰队首");
            //进行淘汰,摘除开头
            head = head.next;
            size--;
        }
    }

    public Node<K, V> peek() {
        return head;
    }

    public void setCapacity(int capacity) {
        throw new UnsupportedOperationException("无法再次设置容量");
    }

    public static class Node<K, V> {
        K key;
        V value;
        Node<K, V> next;

        Node(K key, V value) {
            this.key = key;
            this.value = value;
        }

    }


    public static void main(String[] args) {
        MyLRUImpl<String, String> lru = new MyLRUImpl<>(5, key -> String.valueOf(new Random().nextInt()));
        lru.put("1", "1");//插入
        lru.put("1", "2");//替换
        lru.put("2", "2");//插入第二条
        print(lru.peek());
        lru.get("1");//查询,查看是否交换了顺序
        System.out.println("查询1之后");print(lru.peek());
        lru.get("3");//查询一个缓存中不存在的记录
        System.out.println("查询3之后");print(lru.peek());
        lru.get("4");
        System.out.println("查询4之后");print(lru.peek());
        lru.get("5");
        System.out.println("查询5之后");print(lru.peek());
        lru.get("6");//这时候开始淘汰了
        System.out.println("查询6之后");print(lru.peek());


    }

    public static void print(Node head) {
        while (head != null) {
            System.out.println(head.key + " " + head.value);
            head = head.next;
        }
    }
    
}

/**
 * 抽象工厂,模拟缓存中找不到后在数据库中查询
 */
interface DB<K, V> {
    V getFromDB(K key);
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值