mirror of
https://github.com/duke-git/lancet.git
synced 2025-09-27 03:45:58 +08:00
122 lines
2.3 KiB
Go
122 lines
2.3 KiB
Go
package algorithm
|
|
|
|
type lruNode[K comparable, V any] struct {
|
|
key K
|
|
value V
|
|
pre *lruNode[K, V]
|
|
next *lruNode[K, V]
|
|
}
|
|
|
|
// newLruNode return a lruNode pointer
|
|
func newLruNode[K comparable, V any](key K, value V) *lruNode[K, V] {
|
|
return &lruNode[K, V]{
|
|
key: key,
|
|
value: value,
|
|
pre: nil,
|
|
next: nil,
|
|
}
|
|
}
|
|
|
|
// LRUCache lru cache (thread unsafe)
|
|
type LRUCache[K comparable, V any] struct {
|
|
cache map[K]*lruNode[K, V]
|
|
head *lruNode[K, V]
|
|
tail *lruNode[K, V]
|
|
capacity int
|
|
length int
|
|
}
|
|
|
|
// NewLRUCache creates a LRUCache pointer instance.
|
|
func NewLRUCache[K comparable, V any](capacity int) *LRUCache[K, V] {
|
|
return &LRUCache[K, V]{
|
|
cache: make(map[K]*lruNode[K, V], capacity),
|
|
head: nil,
|
|
tail: nil,
|
|
capacity: capacity,
|
|
length: 0,
|
|
}
|
|
}
|
|
|
|
// Get value of key from lru cache.
|
|
// Play: https://go.dev/play/p/iUynEfOP8G0
|
|
func (l *LRUCache[K, V]) Get(key K) (V, bool) {
|
|
var value V
|
|
|
|
node, ok := l.cache[key]
|
|
if ok {
|
|
l.moveToTail(node)
|
|
return node.value, true
|
|
}
|
|
|
|
return value, false
|
|
}
|
|
|
|
// Put value of key into lru cache.
|
|
// Play: https://go.dev/play/p/iUynEfOP8G0
|
|
func (l *LRUCache[K, V]) Put(key K, value V) {
|
|
node, ok := l.cache[key]
|
|
if !ok {
|
|
newNode := newLruNode(key, value)
|
|
l.cache[key] = newNode
|
|
l.addNode(newNode)
|
|
|
|
if len(l.cache) > l.capacity {
|
|
oldKey := l.deleteNode(l.head)
|
|
delete(l.cache, oldKey)
|
|
}
|
|
} else {
|
|
node.value = value
|
|
l.moveToTail(node)
|
|
}
|
|
l.length = len(l.cache)
|
|
}
|
|
|
|
// Delete item from lru cache.
|
|
func (l *LRUCache[K, V]) Delete(key K) bool {
|
|
node, ok := l.cache[key]
|
|
if ok {
|
|
key := l.deleteNode(node)
|
|
delete(l.cache, key)
|
|
return true
|
|
}
|
|
l.length = len(l.cache)
|
|
return false
|
|
}
|
|
|
|
// Len returns the number of items in the cache.
|
|
func (l *LRUCache[K, V]) Len() int {
|
|
return l.length
|
|
}
|
|
|
|
func (l *LRUCache[K, V]) addNode(node *lruNode[K, V]) {
|
|
if l.tail != nil {
|
|
l.tail.next = node
|
|
node.pre = l.tail
|
|
node.next = nil
|
|
}
|
|
l.tail = node
|
|
if l.head == nil {
|
|
l.head = node
|
|
}
|
|
}
|
|
|
|
func (l *LRUCache[K, V]) deleteNode(node *lruNode[K, V]) K {
|
|
if node == l.tail {
|
|
l.tail = l.tail.pre
|
|
} else if node == l.head {
|
|
l.head = l.head.next
|
|
} else {
|
|
node.pre.next = node.next
|
|
node.next.pre = node.pre
|
|
}
|
|
return node.key
|
|
}
|
|
|
|
func (l *LRUCache[K, V]) moveToTail(node *lruNode[K, V]) {
|
|
if l.tail == node {
|
|
return
|
|
}
|
|
l.deleteNode(node)
|
|
l.addNode(node)
|
|
}
|