Transferred LRU cache code.
This commit is contained in:
parent
a9e47548ad
commit
7b807ae14c
7
ExtraCollectionSharp/ExtraCollectionSharp.csproj
Normal file
7
ExtraCollectionSharp/ExtraCollectionSharp.csproj
Normal file
@ -0,0 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
95
ExtraCollectionSharp/LRUCache.cs
Normal file
95
ExtraCollectionSharp/LRUCache.cs
Normal file
@ -0,0 +1,95 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ExtraCollectionSharp
|
||||
{
|
||||
public class LRUCache<K, V> : IEnumerable<V>
|
||||
{
|
||||
private class Node
|
||||
{
|
||||
public K key;
|
||||
public V value;
|
||||
public Node front;
|
||||
public Node back;
|
||||
}
|
||||
|
||||
public int Size {get { return size; } }
|
||||
public int Count {get { return valueDictionary.Count; } }
|
||||
private readonly int size;
|
||||
private Node top;
|
||||
private Node bottom;
|
||||
private Dictionary<K, Node> valueDictionary;
|
||||
private Action<V> cleanupAction;
|
||||
|
||||
public LRUCache(int size = 100, Action<V> cleanup = null)
|
||||
{
|
||||
this.size = size;
|
||||
valueDictionary = new Dictionary<K, Node>(size);
|
||||
this.cleanupAction = cleanup;
|
||||
}
|
||||
|
||||
private void MoveToTop(K key) {
|
||||
Node node = valueDictionary[key];
|
||||
if (node != null && top != node) {
|
||||
node.front.back = node.back;
|
||||
node.back = top;
|
||||
node.front = null;
|
||||
top = node;
|
||||
}
|
||||
}
|
||||
|
||||
private Node AddToTop(K key, V value) {
|
||||
Node node = new Node();
|
||||
node.front = null;
|
||||
node.back = top;
|
||||
node.value = value;
|
||||
node.key = key;
|
||||
top = node;
|
||||
if (bottom == null) {
|
||||
bottom = node;
|
||||
} else if (valueDictionary.Count == Size) {
|
||||
valueDictionary.Remove(bottom.key);
|
||||
cleanupAction?.Invoke(bottom.value);
|
||||
bottom = bottom.front;
|
||||
}
|
||||
valueDictionary[key] = node;
|
||||
return node;
|
||||
}
|
||||
|
||||
public V Use(K key, Func<V> generate) {
|
||||
if (generate == null) throw new ArgumentNullException("generate");
|
||||
Node value = null;
|
||||
if (valueDictionary.ContainsKey(key)) {
|
||||
value = valueDictionary[key];
|
||||
MoveToTop(key);
|
||||
} else {
|
||||
value = AddToTop(key, generate());
|
||||
}
|
||||
return value.value;
|
||||
}
|
||||
|
||||
public bool IsCached(K key) {
|
||||
return valueDictionary.ContainsKey(key);
|
||||
}
|
||||
|
||||
public void Clear() {
|
||||
top = null;
|
||||
bottom = null;
|
||||
valueDictionary.Clear();
|
||||
}
|
||||
|
||||
public IEnumerator<V> GetEnumerator()
|
||||
{
|
||||
foreach (Node node in valueDictionary.Values)
|
||||
{
|
||||
yield return node.value;
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user