61 lines
1.1 KiB
Go
61 lines
1.1 KiB
Go
package lrucache
|
|
|
|
import (
|
|
"container/list"
|
|
)
|
|
|
|
type Creator func(key string) interface{}
|
|
|
|
type cacheKey struct {
|
|
Value interface{}
|
|
DoubleLinkedListNode *list.Element
|
|
}
|
|
|
|
type LRUCache struct {
|
|
cache map[string]*cacheKey
|
|
ddl *list.List
|
|
creator Creator
|
|
length int
|
|
}
|
|
|
|
func New(creator Creator, length int) *LRUCache {
|
|
return &LRUCache{
|
|
cache: make(map[string]*cacheKey),
|
|
creator: creator,
|
|
ddl: new(list.List).Init(),
|
|
length: length,
|
|
}
|
|
}
|
|
|
|
func (lru *LRUCache) add(key string, val interface{}) interface{} {
|
|
lru.ddl.PushFront(key)
|
|
lru.cache[key] = &cacheKey{val, lru.ddl.Front()}
|
|
return val
|
|
}
|
|
|
|
func (lru *LRUCache) Size() int {
|
|
return len(lru.cache)
|
|
}
|
|
|
|
func (lru *LRUCache) removeExtraKeys() {
|
|
if lru.ddl.Len() < lru.length {
|
|
return
|
|
}
|
|
for e := lru.ddl.Back(); lru.ddl.Len() > lru.length; {
|
|
delete(lru.cache, e.Value.(string))
|
|
be := e.Prev()
|
|
lru.ddl.Remove(e)
|
|
e = be
|
|
}
|
|
}
|
|
|
|
func (lru *LRUCache) Get(key string) interface{} {
|
|
if val, ok := lru.cache[key]; ok {
|
|
lru.ddl.MoveToFront(val.DoubleLinkedListNode)
|
|
return val.Value
|
|
}
|
|
ret := lru.add(key, lru.creator(key))
|
|
lru.removeExtraKeys()
|
|
return ret
|
|
}
|