我需要一个CircularBuffer IDictionary。任何人都可以向我指出一个良好的开源实现。
这是一个具有最大容量的IDictionary,比如配置为100个项目,当添加项目101时,将从字典中弹出/删除原始的第一个项目,从而确保项目计数永远不会超过100个。
由于
答案 0 :(得分:12)
要保持O(1)插入(删除最旧的项目超过100)和O(1)查找,您需要一个实现IDictionary 和的类保留内部有序列表。如果内存更受关注,那么像SortedList
这样的BST实现可能更合适。无论如何,您的课程将同时包含T[]
和Dictionary<T,K>
(或SortedList<T,K>
)。执行您自己的循环缓冲区索引(简单),并在添加,删除等方法中保持两个集合的最新状态。你会:
将其设为通用并实施IDictionary<T,K>
和IDictionary
,因为没有理由不这样做,您将获得性能优势。
一个主要考虑因素:您如何处理重复密钥?我假设你实际上不能保留重复项,所以:
Count
,然后使用this[key]
索引器插入密钥。如果大小增加,则检查列表是否已具有最大容量,从列表和字典中删除前项并将新项添加到后面。如果字典的大小没有增加,请将项目从列表中的现有位置移动到列表的后面。最后,请注意内部列表保留键,而不是值。这是为了确保在超出列表容量时O(1)出列。
答案 1 :(得分:4)
在谷歌搜索五分钟后发现两个:
答案 2 :(得分:3)
我不知道任何这样的实现,但它自己听起来并不难。由于字典没有任何固有顺序,因此字典中的键或值类型需要具有一些属性,表示它插入字典的顺序。然后,在覆盖Add
方法时,它可以检查计数是否为最大值。如果是,则查看现有的键值对以查找其insert-order属性最低的那个,并将其替换为新的键值对。否则,照常插入新的键值对。
答案 3 :(得分:2)
我不久前在C#3.0中编写了一个循环缓冲区的完整实现,并在CodePlex上发布了源代码。它遵循BCL设计指南,并实现System.Collections
的所有适当接口。
我认为应该很容易适应使用Dictionary<TKey, TValue>
作为支持集合而不是List<T>
。
答案 4 :(得分:0)
这个怎么样:
public class CircularDictionary<TKey, TValue> : Dictionary<TKey, TValue>
{
private Queue<TKey> m_ItemInsertList = new Queue<TKey>();
private int m_ItemsToHold = 100;
public int ItemsToHold
{
get { return m_ItemsToHold; }
set {
if (value < 1)
throw new ArgumentException("Items to hold must be at least 1");
m_ItemsToHold = value;
}
}
public new void Add(TKey key, TValue value)
{
base.Add(key, value);
if (m_ItemInsertList.Count == m_ItemsToHold)
base.Remove(m_ItemInsertList.Dequeue());
m_ItemInsertList.Enqueue(key);
}
}
答案 5 :(得分:0)
我通过System.Data.Sqlite(http://sqlite.phxsoftware.com/)包装器使用SQLite数据库表实现了类似的功能。您可以将其存储在磁盘上或作为内存数据库。您可以选择是否具有唯一键,并让数据库引擎为您处理索引。您甚至可以为每个键设置多个值。
当您写入表格时,请检查您是否处于100个记录限制,如果是,则在插入之前删除。如果要保留唯一键,SQLite支持“插入或替换”命令。也许这不像自定义IDictionary派生那么优雅,但它可以工作,它很灵活,而且很容易在线程之间共享。