2013-02-03 48 views
1

可能重複:
Is it there any LRU implementation of IDictionary?的字典數據結構與最大尺寸

我在尋找一種數據結構,就像一本字典,但只能包含密鑰集數值對。將鍵值對添加到已滿的字典中時,最近未訪問的鍵值對將被刪除。

這樣的事情對於C#已經存在嗎?

我記得爲操作系統類實現類似的東西,數據結構被用來決定哪部分內存應該分頁到磁盤。這是通過將參考位與每個訪問該對時設置爲true的每個鍵值對相關聯來完成的。當需要刪除一對時,鍵值對將被迭代,直到發現一個關鍵字對的參考位設置爲false。迭代的每對參考位將被設置爲false,最後一個參考位將被刪除。

如果一個數據結構在C#中不存在,那麼我描述的算法是否是實現它的好方法?

回答

0

貌似沒有任何已經在.NET Framework所以這裏的這個實現是什麼我最終使用

using System.Collections.Generic; 
using System.Linq; 

namespace MyProject.Util 
{ 
public class LruCache<Key, Value> 
{ 
    public delegate Value ValueCreator(); 

    Dictionary<Key, ValueWithReference> cache; 

    //The maximum number of elements that can fit in the cache. 
    int maxCacheSize; 

    IEnumerator<Value> valueRemover; 

    public LruCache(int maxCacheSize) { 
     this.cache = new Dictionary<Key, ValueWithReference>(); 
     this.maxCacheSize = maxCacheSize; 
     this.valueRemover = GetKeyValuePairRemover().GetEnumerator(); 
    } 

    /// <summary> 
    /// Gets the value associated with the specified key. If it doesn't exist in the cache 
    /// then it will be created with createValue() and added to the cache. 
    /// </summary> 
    public Value GetAndAddValue(Key key, ValueCreator createValue) { 
     if (this.cache.ContainsKey(key) == false) 
     { 
      while (this.cache.Count >= this.maxCacheSize) { 
       this.valueRemover.MoveNext(); 
      } 

      this.cache[key] = new ValueWithReference(createValue()); 
     } 

     this.cache[key].recentlyUsed = true; 
     return this.cache[key].value; 

    } 

    protected IEnumerable<Value> GetKeyValuePairRemover() { 
     while (true) { 
      List<Key> keyList = this.cache.Keys.ToList(); 

      foreach(Key key in keyList) { 
       if (this.cache[key].recentlyUsed) 
       { 
        this.cache[key].recentlyUsed = false; 
       } 
       else { 
        Value removedValue = this.cache[key].value; 
        this.cache.Remove(key); 
        yield return removedValue; 
       } 
      } 

     } 
    } 

    protected class ValueWithReference 
    { 
     public Value value; 
     public bool recentlyUsed; 

     public ValueWithReference(Value value) 
     { 
      this.value = value; 
      this.recentlyUsed = true; 
     } 
    } 
} 
}