2022-02-10 22:06:57 +00:00
|
|
|
//go:build !solution
|
2020-03-12 09:32:51 +00:00
|
|
|
|
|
|
|
package lrucache
|
|
|
|
|
2024-06-05 00:46:41 +00:00
|
|
|
import (
|
|
|
|
"container/list"
|
|
|
|
)
|
|
|
|
|
|
|
|
type cacheEntry struct {
|
|
|
|
key int
|
|
|
|
value int
|
|
|
|
}
|
|
|
|
|
|
|
|
type lrucache struct {
|
|
|
|
cap int
|
|
|
|
data map[int]*list.Element
|
|
|
|
recentEntries *list.List
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *lrucache) isFull() bool {
|
|
|
|
return c.recentEntries.Len() == c.cap
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *lrucache) Get(key int) (int, bool) {
|
|
|
|
e, ok := c.data[key]
|
|
|
|
if !ok {
|
|
|
|
return 0, false
|
|
|
|
}
|
|
|
|
entry := c.recentEntries.Remove(e).(cacheEntry)
|
|
|
|
c.data[key] = c.recentEntries.PushBack(entry)
|
|
|
|
return entry.value, true
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *lrucache) Set(key int, value int) {
|
|
|
|
if c.cap == 0 {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
e, ok := c.data[key]
|
|
|
|
if ok {
|
|
|
|
c.recentEntries.Remove(e)
|
|
|
|
c.data[key] = c.recentEntries.PushBack(cacheEntry{key, value})
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if c.isFull() {
|
|
|
|
removed := c.recentEntries.Remove(c.recentEntries.Front()).(cacheEntry)
|
|
|
|
delete(c.data, removed.key)
|
|
|
|
}
|
|
|
|
c.data[key] = c.recentEntries.PushBack(cacheEntry{key, value})
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *lrucache) Range(f func(key, value int) bool) {
|
|
|
|
for e := c.recentEntries.Front(); e != nil; e = e.Next() {
|
|
|
|
entry := e.Value.(cacheEntry)
|
|
|
|
if !f(entry.key, entry.value) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *lrucache) Clear() {
|
|
|
|
for k := range c.data {
|
|
|
|
delete(c.data, k)
|
|
|
|
}
|
|
|
|
c.recentEntries.Init()
|
|
|
|
}
|
|
|
|
|
2020-03-12 09:32:51 +00:00
|
|
|
func New(cap int) Cache {
|
2024-06-05 00:46:41 +00:00
|
|
|
return &lrucache{cap, make(map[int]*list.Element), list.New()}
|
2020-03-12 09:32:51 +00:00
|
|
|
}
|