【JS算法】LRU 缓存

2022-04-27  本文已影响0人  wyc0859

先复习下迭代器和可迭代对象

迭代器是确使用户可在容器对象(如链表、数组)上遍访的对象,使用该接口无需关心对象的内部实现细节

const arr = [1, 2, 3, 4, 5, 6]
const iterator = arr[Symbol.iterator]() // 执行一个迭代器
console.log(iterator) // Object [Array Iterator] {}

console.log(iterator.next()) //{ value: 1, done: false }
console.log(iterator.next()) //{ value: 2, done: false }
let next = iterator.next()

while (!next.done) {
  console.log(next.value) //分别打印 3 4 5 6
  next = iterator.next()
}

可迭代对象 它和迭代器是不同的概念,这个对象必须实现@iterator 方法,在代码中我们使用 Symbol.iterator 访问该属性

const iteratorObj = {
  names: ['a', 'b', 'c', 'd'],
  index: 0,
  [Symbol.iterator]: function () {
    return {
      // 这边使用箭头函数,以使this指向iteratorObj
      next: () => {
        if (this.index < this.names.length) {
          // [this.index++] 是先调[this.index],再++
          return { value: this.names[this.index++], done: false }
        } else {
          return { value: 'no name', done: true }
}}}}}
const iterator1 = iteratorObj[Symbol.iterator]()
console.log(iterator1) //[Map Iterator] { 'a', 'b', 'c' }

console.log(iterator1.next()) //{ value: 'a', done: false }
console.log(iterator1.next()) //{ value: 'b', done: false }
let next2 = iterator1.next()
while (!next2.done) {
  console.log(next2.value) //分别打印 c d
  next2 = iterator1.next()
}

Map对象.keys() 返回的是一个迭代对象

let cache = new Map()
cache.set('a', 1)
cache.set('b', 2)
cache.set('c', 3)
const data = cache.keys()
console.log(data) //[Map Iterator] { 'a', 'b', 'c' }

//错误用法
console.log(cache.keys().next()) //{ value: 'a', done: false }
console.log(cache.keys().next()) //{ value: 'a', done: false }

//正确
console.log(data.next()) //{ value: 'a', done: false }
console.log(data.next()) //{ value: 'b', done: false }
console.log(data.next()) //{ value: 'c', done: false }

LRU 缓存

它是一种缓存淘汰机制,顾名思义,将最近使用次数最少的缓存淘汰

如何设计一个简单的LRU缓存算法?

举个栗子,内存容量大小为2,按照key-value形式存储,结构的前面(最右侧)为最近最常使用的节点,后面(最左侧)为最近最少使用的节点。

LRU有两个操作:get和put,每次get和put操作都将查询的值变为最近最常使用的节点,当put容量已满时,删除最近最少使用的节点

var LRUCache = function (capacity) {
  this.cache = new Map()
  this.max = capacity //缓存最大个数
}

//原型链上挂get方法
LRUCache.prototype.get = function (key) {
  if (this.cache.has(key)) {
    let tmp = this.cache.get(key)
    this.cache.delete(key)
    this.cache.set(key, tmp) //删除后,重新放到最前面
    return tmp
  }
  return -1 //题目要求返回-1
}

LRUCache.prototype.put = function (key, value) {
  if (this.cache.has(key)) {
    this.cache.delete(key) //删除后,重新放到最前面
  } else if (this.cache.size >= this.max) {
    //新增就要有缓存的淘汰机制
    this.cache.delete(this.cache.keys().next().value)
  }
  this.cache.set(key, value)
}

let cache = new LRUCache(2)
cache.put(1, 1) // 缓存是 {1=1}
cache.put(2, 2) // 缓存是 {1=1, 2=2}
cache.get(1) // 返回 1 变{2=2, 1=1}
cache.put(3, 3) // 该操作会使得关键字 2 作废,缓存是 {1=1, 3=3}
cache.get(2) // 返回 -1 (未找到)
cache.put(4, 4) // 该操作会使得关键字 1 作废,缓存是 {3=3,4=4}
cache.get(1) // 返回 -1 (未找到)
cache.get(3) // 返回 3  变{4=4, 3=3}
cache.get(4) // 返回 4  变{3=3, 4=4}

vue中keep-alive 用到的就是 LRU 缓存

上一篇下一篇

猜你喜欢

热点阅读