diff --git a/2q.go b/2q.go index 1f0055b..5e00d9a 100644 --- a/2q.go +++ b/2q.go @@ -181,6 +181,16 @@ func (c *TwoQueueCache[K, V]) Keys() []K { return append(k1, k2...) } +// Values returns a slice of the values in the cache. +// The frequently used values are first in the returned slice. +func (c *TwoQueueCache[K, V]) Values() []V { + c.lock.RLock() + defer c.lock.RUnlock() + v1 := c.frequent.Values() + v2 := c.recent.Values() + return append(v1, v2...) +} + // Remove removes the provided key from the cache. func (c *TwoQueueCache[K, V]) Remove(key K) { c.lock.Lock() diff --git a/2q_test.go b/2q_test.go index fd4c0e9..0b979df 100644 --- a/2q_test.go +++ b/2q_test.go @@ -236,6 +236,11 @@ func Test2Q(t *testing.T) { t.Fatalf("bad key: %v", k) } } + for i, v := range l.Values() { + if v != i+128 { + t.Fatalf("bad key: %v", v) + } + } for i := 0; i < 128; i++ { if _, ok := l.Get(i); ok { t.Fatalf("should be evicted") diff --git a/arc.go b/arc.go index a255aae..84c0b72 100644 --- a/arc.go +++ b/arc.go @@ -211,6 +211,15 @@ func (c *ARCCache[K, V]) Keys() []K { return append(k1, k2...) } +// Values returns all the cached values +func (c *ARCCache[K, V]) Values() []V { + c.lock.RLock() + defer c.lock.RUnlock() + v1 := c.t1.Values() + v2 := c.t2.Values() + return append(v1, v2...) +} + // Remove is used to purge a key from the cache func (c *ARCCache[K, V]) Remove(key K) { c.lock.Lock() diff --git a/arc_test.go b/arc_test.go index 7171d41..98190c8 100644 --- a/arc_test.go +++ b/arc_test.go @@ -308,6 +308,11 @@ func TestARC(t *testing.T) { t.Fatalf("bad key: %v", k) } } + for i, v := range l.Values() { + if v != i+128 { + t.Fatalf("bad value: %v", v) + } + } for i := 0; i < 128; i++ { if _, ok := l.Get(i); ok { t.Fatalf("should be evicted") diff --git a/lru.go b/lru.go index 32d0417..a2655f1 100644 --- a/lru.go +++ b/lru.go @@ -233,6 +233,14 @@ func (c *Cache[K, V]) Keys() []K { return keys } +// Values returns a slice of the values in the cache, from oldest to newest. +func (c *Cache[K, V]) Values() []V { + c.lock.RLock() + values := c.lru.Values() + c.lock.RUnlock() + return values +} + // Len returns the number of items in the cache. func (c *Cache[K, V]) Len() int { c.lock.RLock() diff --git a/lru_test.go b/lru_test.go index 3081a5b..9da0b23 100644 --- a/lru_test.go +++ b/lru_test.go @@ -95,6 +95,11 @@ func TestLRU(t *testing.T) { t.Fatalf("bad key: %v", k) } } + for i, v := range l.Values() { + if v != i+128 { + t.Fatalf("bad value: %v", v) + } + } for i := 0; i < 128; i++ { if _, ok := l.Get(i); ok { t.Fatalf("should be evicted") diff --git a/simplelru/lru.go b/simplelru/lru.go index b6731af..ac25664 100644 --- a/simplelru/lru.go +++ b/simplelru/lru.go @@ -129,6 +129,17 @@ func (c *LRU[K, V]) Keys() []K { return keys } +// Values returns a slice of the values in the cache, from oldest to newest. +func (c *LRU[K, V]) Values() []V { + values := make([]V, len(c.items)) + i := 0 + for ent := c.evictList.back(); ent != nil; ent = ent.prevEntry() { + values[i] = ent.value + i++ + } + return values +} + // Len returns the number of items in the cache. func (c *LRU[K, V]) Len() int { return c.evictList.length() diff --git a/simplelru/lru_interface.go b/simplelru/lru_interface.go index 3cbf02b..043b8bc 100644 --- a/simplelru/lru_interface.go +++ b/simplelru/lru_interface.go @@ -32,6 +32,9 @@ type LRUCache[K comparable, V any] interface { // Returns a slice of the keys in the cache, from oldest to newest. Keys() []K + // Values returns a slice of the values in the cache, from oldest to newest. + Values() []V + // Returns the number of items in the cache. Len() int diff --git a/simplelru/lru_test.go b/simplelru/lru_test.go index 79e9457..a6b247f 100644 --- a/simplelru/lru_test.go +++ b/simplelru/lru_test.go @@ -34,6 +34,11 @@ func TestLRU(t *testing.T) { t.Fatalf("bad key: %v", k) } } + for i, v := range l.Values() { + if v != i+128 { + t.Fatalf("bad value: %v", v) + } + } for i := 0; i < 128; i++ { if _, ok := l.Get(i); ok { t.Fatalf("should be evicted")