自定义 LRU、LFU Cache(Java 版)-前置准备

时间:2024-03-30 12:10:05

定义 BaseCache 接口,包含 put、get 方法和 Cache 实际存储的数据结构等

public interface BaseCache<K, V> {

    /**
     * 将 <Key, Val> 组装成 Node 节点放入 Cache 中
     *
     * @param key CacheKey
     * @param val CacheValue
     */
    void put(K key, V val);

    /**
     * 获取指定 CacheKey 对应的 Value,不存在返回 null
     *
     * @param key CacheKey
     * @return CacheValue
     */
    V get(K key);

    /**
     * Cache 实际的数据结构
     *
     * @param <K> Cache Key
     * @param <V> Cache Value
     */
    class DoubleLinkedList<K, V> {

        Node<K, V> head;
        Node<K, V> tail;

        DoubleLinkedList() {
            head = new Node<>();
            tail = new Node<>();
            head.next = tail;
            tail.prev = head;
        }

        /**
         * 添加节点到链表的末尾
         *
         * @param node 待添加的节点
         */
        void addLast(Node<K, V> node) {
            node.prev = tail.prev;
            node.next = tail;
            tail.prev.next = node;
            tail.prev = node;
        }

        /**
         * 删除指定节点
         *
         * @param node 待删除的节点
         */
        void remove(Node<K, V> node) {
            node.prev.next = node.next;
            node.next.prev = node.prev;
        }

        void prettyPrint() {
            Node<K, V> current = head.next;

            while (current != tail) {
                System.out.print("CacheKey: " + current.key + ", CacheValue: " + current.val);
                current = current.next;
                if (current != tail) {
                    System.out.println();
                    System.out.print("   <=>   ");
                }
                System.out.println();
            }
        }

    }

    /**
     * DoubleLinkedList 中实际存储的元素类型
     *
     * @param <K> Node Key
     * @param <V> Node Value
     */
    class Node<K, V> {

        K key;
        V val;
        Node<K, V> next;
        Node<K, V> prev;

        Node() {
        }

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

    }

}

定义 Person 类【CacheValue】和 PersonCacheUtils 用来辅助测试

public class Person {

    private Long id;

    private String name;

    private Integer age;

    public Person(String name, Integer age) {
        this.id = System.currentTimeMillis() + (long) (Math.random() * 1000);
        this.name = name;
        this.age = age;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

}
public class PersonCacheUtils {

    private static final String CACHE_KEY_PREFIX = "Person_";

    private static final String PERSON_NAME_PREFIX = "Person-";

    public static void addPersonsToCache(BaseCache<String, Person> cache, int personCount) {
        Random random = new Random();

        for (int i = 0; i < personCount; i++) {
            String name = PERSON_NAME_PREFIX + UUID.randomUUID().toString().substring(0, 4);
            Integer age = 10 + random.nextInt(50);
            Person person = new Person(name, age);
            cache.put(getCacheKey(person.getId()), person);
        }
    }

    public static String getCacheKey(Long id) {
        return CACHE_KEY_PREFIX + id;
    }

}