整日与浏览器打交道的前端老司机们,如果还不知道浏览器的历史记录是如何保存的,不妨花几分钟时间来了解下 LRU 算法,那么,
什么是 LRU 算法?
LRU(Least recently used,最近最少使用)是一种常用的页面置换算法,LRU 算法根据数据的历史访问记录来进行淘汰数据,其核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高”。
LRU 算法的使用场景:
- 比如浏览器的历史记录缓存
- 缓存服务,比如 redis 缓存
- 用 hash 表作为底层结构的数据库
算法核心原理:有一块大小固定的内存,用于存放我们最近访问的页面。我们不断往内存中添加页面,当内存满了,需要删除内存中最早访问的页面,让新页面插入内存进行缓存。这样一个不断添加和删除网页的过程就是 LRU 算法。
Map 实现 LRU 算法
我们使用 SE6 Map 数据结构存储数据。Map 自带的 get、set、delete、has 方法能方便我们对数据进行增删改查操作。
实现思路: 1、首先定义一个类 LRUfunc ,我们设置一个最大长度 length,用来限制 map 的大小,模拟大小固定的内存。 2、然后,添加 get 方法,进行页面查询。做两件事:历史记录有页面时,先将该页面删除;再将页面插入到 map 的头部,表示最新访问了该页面。 3、再者,添加 set 方法,进行页面的添加处理。新增页面时,查询 map ,如果历史记录中该页面已存在,先把页面删除,再把页面放到 map 头部,表示最新访问。如果页面不存在时,先看 map 大小是否已经超出设定长度,超出长度限制时表示内存满了,我们需要先把 map 尾部的页面删除,然后将新增的页面插入到 map 的头部,表示最新访问了该页面。
话不多说,直接上代码:
/**
* 定义 LRUfunc 类存储数据,实现完成一个 LRU 缓存
*/
class LRUfunc {
constructor(length){
this.length = length
this.map = new Map()
}
// 获取数据
get(data) {
if(!this.map.get(data)) return null
this.map.delete(data)
this.map.set(data,data)
}
// 设置数据
set(data) {
if(this.map.has(data)){
// 如果内存中有页面,先把页面删除,再把页面放到内存最新位置
this.map.delete(data)
}
if(this.map.size + 1 > this.length) {
this.map.delete(this.map.keys().next().value)
}
this.map.set(data, data)
}
}
const lru = new LRUfunc(3)
lru.set('zhangsan')
lru.set('lisi')
lru.set('wangwu')
console.log(lru)
向 map 添加 3 个页面,输出:
再访问新页面 lru.set(''newpage),map.size 依旧是 3 ,输出:
写在结尾:如果你觉得这篇文章对你有那么一咻咻点用处,不妨给个赞,你的支持和鼓励是我不断分享的动力!