招商银行(深圳),复盘,一面算法

算法:
java中的缓存你是用哪些实现的?内存缓存?LRU算法淘汰机制?用java中的什么数据结构实现?

设计一个简单的缓存的一个淘汰机制,比如说我举个例子,这个缓存只允许上限为十个,超出十个之后,你就要有一个淘汰机制策略?把老的剔除出去?

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * 简单LRU缓存(上限10个元素,满时淘汰最近最少使用的数据)
 * @param <K> 缓存键类型
 * @param <V> 缓存值类型
 */
public class SimpleLRUCache<K, V> {
    // 缓存底层存储:LinkedHashMap,开启“按访问顺序排序”
    private final LinkedHashMap<K, V> cacheMap;
    // 缓存最大容量(题目要求10)
    private final int MAX_CAPACITY = 10;

    // 构造函数:初始化LinkedHashMap,开启访问顺序排序
    public SimpleLRUCache() {
        // 参数说明:
        // 1. initialCapacity:初始容量(设为10,和最大容量一致,避免扩容)
        // 2. loadFactor:负载因子(0.75是默认最优值,避免频繁扩容)
        // 3. accessOrder:true=按访问顺序排序,false=按插入顺序排序(LRU必须设为true)
        cacheMap = new LinkedHashMap<>(MAX_CAPACITY, 0.75f, true) {
            // 重写此方法:判断是否需要删除最老元素
            @Override
            protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
                // 当缓存size > 最大容量时,返回true,自动删除最老元素(eldest就是最老的)
                return size() > MAX_CAPACITY;
            }
        };
    }

    // 1. 存缓存:key不存在则新增,存在则更新值(更新后会自动移到链表尾部,标记为“最近使用”)
    public void put(K key, V value) {
        cacheMap.put(key, value);
    }

    // 2. 取缓存:获取值的同时,会自动把该元素移到链表尾部(标记为“最近使用”)
    public V get(K key) {
        return cacheMap.get(key); // 若key不存在,返回null
    }

    // 3. 删缓存:手动删除指定key的缓存
    public void remove(K key) {
        cacheMap.remove(key);
    }

    // 4. 辅助方法:查看当前缓存所有数据(用于测试,看淘汰效果)
    public void printCache() {
        System.out.println("当前缓存数据(顺序:从左到右是“最久未使用”到“最近使用”):");
        for (Map.Entry<K, V> entry : cacheMap.entrySet()) {
            System.out.print(entry.getKey() + "=" + entry.getValue() + " ");
        }
        System.out.println("\n当前缓存大小:" + cacheMap.size());
    }

    // 测试:验证LRU淘汰效果
    public static void main(String[] args) {
        SimpleLRUCache<Integer, String> cache = new SimpleLRUCache<>();

        // 1. 先存10个元素(达到最大容量)
        for (int i = 1; i <= 10; i++) {
            cache.put(i, "value" + i);
        }
        System.out.println("=== 存满10个元素后 ===");
        cache.printCache(); // 输出:1=value1 2=value2 ... 10=value10(1是最老,10是最新)

        // 2. 访问第3个元素(标记为“最近使用”,会移到尾部)
        cache.get(3);
        System.out.println("\n=== 访问key=3后 ===");
        cache.printCache(); // 输出:1=value1 2=value2 4=value4 ... 3=value3(3移到尾部)

        // 3. 再存第11个元素(触发淘汰,删除最老的key=1)
        cache.put(11, "value11");
        System.out.println("\n=== 存第11个元素后(触发淘汰) ===");
        cache.printCache(); // 输出:2=value2 4=value4 ... 11=value11(key=1被淘汰,size保持10)
    }
}

// 伪码:手动实现LRU缓存(上限10)
class SimpleLRUCache {
    // 缓存实体:存key、value、最后访问时间戳
    class CacheItem {
        K key;
        V value;
        long lastAccessTime; // 毫秒级时间戳,记录最后访问时间
    }

    CacheItem[] cacheArray; // 存储缓存的数组(大小10)
    int currentSize; // 当前缓存元素个数

    // 初始化:数组大小10,currentSize=0
    function SimpleLRUCache() {
        cacheArray = new CacheItem[10];
        currentSize = 0;
    }

    // 存缓存
    function put(K key, V value) {
        1. 检查key是否已存在:
           - 若存在:更新对应value,同时更新lastAccessTime为当前时间;
           - 若不存在:
               a. 若currentSize < 10:直接把新CacheItem放入数组,currentSize+1;
               b. 若currentSize == 10:找出数组中lastAccessTime最小的元素(最久未使用),替换成新CacheItem;
    }

    // 取缓存
    function get(K key) {
        1. 遍历数组找对应key:
           - 若找到:更新其lastAccessTime为当前时间,返回value;
           - 若没找到:返回null;
    }

    // 淘汰逻辑:在put满10个时,调用此方法找最久未使用元素
    function findOldestItem() {
        1. 遍历数组,记录lastAccessTime最小的元素索引;
        2. 返回该元素索引,用于后续替换;
    }
}
全部评论

相关推荐

01-28 16:12
中南大学 Java
几年前还没有chatgpt的时候,刷题真的是很痛苦。刷不出来只能看题解,题解有几个问题:第一个是每次看的写题解的人都不一样,很难有一个统一的思路;第二个也是最重要的是,题解只提供了作者自己的思路,但是没有办法告诉你你的思路哪里错了。其实很少有错误的思路,我只是需要被引导到正确的思路上面去。所以传统题解学习起来非常困难,每次做不出来难受,找题解更难受。但是现在chatgpt能做很多!它可以这样帮助你&nbsp;-1.&nbsp;可以直接按照你喜欢的语言生成各种解法的题解和分析复杂度。2.&nbsp;把题和你写的代码都发给它,它可以告诉你&nbsp;你的思路到底哪里有问题。有时候我发现我和题解非常接近,只是有一点点🤏想错了。只要改这一点点就是最优解。信心倍增。3.&nbsp;如果遇到不懂的题解可以一行一行询问为什么要这样写,chatgpt不会嫌你烦。有时候我觉得自己的range写错了,其实那样写也没错,只是chat老师的题解有一点优化,这个它都会讲清楚。4.&nbsp;它可以帮你找可以用同类型解法来做的题。然后它可以保持解法思路不变,用一个思路爽刷一个类型的题。如果题目之间思路又有变化,它会告诉你只有哪里变了,其他的地方还是老思路。5.&nbsp;它也可以直接帮你总结模板,易错点。经过chat老师的指导,我最大的改变是敢刷题了。之前刷题需要先找某一个人写的算法题repo,然后跟着某一个人他的思路刷他给的几个题。如果想写别的题,套用思路失败了,没有他的题解,也不知道到底哪里错了;看别人的题解,思路又乱了。这个问题在二分查找和dp类型的题里面特别常见。但是现在有chat老师,他会针对我的代码告诉我我哪里想错了,应该怎么做;还按照我写代码的习惯帮我总结了一套属于我的刷题模板。每天写题全是正反馈!
牛客981:不刷才是爽
AI时代的工作 VS 传...
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务