大厂常见面试题: 实现Lru缓存机制

文章目录

  • 前言
  • 一、c++ 实现简易版LruCache
    • List
    • unordered_map
  • 二、Java 实现LruCache


前言

LruCache 也叫 最近最少使用缓存,在生产中经常使用到,用作内存缓存,配合redis可以实现二级缓存,提高服务器的处理性能,而在面试中,缓存是经常被问到的,如果候选人能讲出自己实现那么是很大加分项。

解题思路:
采用 哈希表 + 双向链表

双向链表按照被使用的顺序存储了这些键值对,靠近头部的键值对是最近使用的,而靠近尾部的键值对是最久未使用的。
哈希表即为普通的哈希映射,通过缓存数据的键映射到其在双向链表中的位置。

提示:以下是本篇文章正文内容,下面案例可供参考

一、c++ 实现简易版LruCache

主要运用数据结构:list、unordered_map

List

采用链表方式来记录数据的先后顺序:
1、当链表数据满时(缓存容量),删除队尾数据
2、放入数据时,如果数据已存在列表,那么使用splice方法将数据替换到表头

unordered_map

使用unordered_map存储k-v键值对,用于查找缓存数据
1、unordered_map底层采用哈希表结构存储,其k-v值是无序的

demo:

#include 
#include 

using namespace std;

class LruCache {
private :
	//pair->first 对应map的key
	//pair->second 对应map的value
	list<pair<int, int>> _values;

	//哈希表存储键值在链表中的位置
	unordered_map<int, list<pair<int,int>>::iterator> _container;

	int _capacity;

public:
	LruCache(int capacity) {
		_capacity = capacity;
	}

	int Get(int key) {
		//从哈希表中获取键值
		auto value = _container.find(key);
		if (_container.end() == value) {
			return -1;
		}
		//将哈希表key指向的list节点迁移到链表的表头
		_values.splice(_values.begin(), _values, value->second);

		//pair的second值是键值对的value
		return value->second->second;
	}

	void Put(int key, int value) {
		auto oldValue = _container.find(key);
		if (_container.end() != oldValue) {
			//更新缓存数据
			oldValue->second->second = value;
			//将哈希表key指向的list节点迁移到链表的表头
			_values.splice(_values.begin(), _values, oldValue->second);
			return;
		}

		//当容量超出时
		if (_container.size() == _capacity) {
			//获取链表尾节点,释放其位置放置新数据
			auto oldValue = _values.back();
			//删掉哈希表索引
			_container.erase(oldValue.first);
			//删除索引指向数据
			_values.pop_back();
		}

		_values.emplace_front(key, value);
		_container[key] = _values.begin();
	}
};

二、Java 实现LruCache

相比于C++ 需要两个结构体,Java提供了 LinkedHashMap,其可以设置数据是按插入顺序还是访问顺序进行排序。

 Map<String, String> linkedHashMap = new LinkedHashMap<>(16, 0.75f, true);

这里设置true表示位访问顺序,而其默认值位false即位插入顺序

关于LinkedHashMap的原理可以查看
简书

你可能感兴趣的:(C/C++,面试,redis,java,c++)