diff --git a/lrucache/lru.go b/lrucache/lru.go index 7cdaedc..5cd4c48 100644 --- a/lrucache/lru.go +++ b/lrucache/lru.go @@ -2,6 +2,68 @@ package lrucache -func New(cap int) Cache { - panic("implement me") +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() +} + +func New(cap int) Cache { + return &lrucache{cap, make(map[int]*list.Element), list.New()} }