我需要一个 CircularBuffer IDictionary。谁能给我指出一个好的开源实现。
因此,具有最大容量的 IDictionary,例如配置为 100 个项目,当添加项目 101 时,会从字典中弹出/删除原始第一个项目,从而确保项目计数永远不会超过 100。
谢谢
我需要一个 CircularBuffer IDictionary。谁能给我指出一个好的开源实现。
因此,具有最大容量的 IDictionary,例如配置为 100 个项目,当添加项目 101 时,会从字典中弹出/删除原始第一个项目,从而确保项目计数永远不会超过 100。
谢谢
要保持 O(1) 插入(删除超过 100 的最旧项目)和 O(1) 查找,您需要一个实现 IDictionary并保持内部有序列表的类。如果内存更受关注,则 BST 实现SortedList
可能更合适。无论如何,您的课程将同时包含 aT[]
和 a Dictionary<T,K>
(或SortedList<T,K>
)。做你自己的循环缓冲区索引(简单),并在添加、删除等方法中保持两个集合都是最新的。你将拥有:
使其通用并实施IDictionary<T,K>
,IDictionary
因为没有理由不这样做,您将获得性能优势。
一个主要考虑因素:您如何处理重复键?我假设您实际上不能保留重复项,因此:
Count
插入键。this[key]
如果大小增加,则检查列表是否已经具有最大容量,从列表和字典中删除前面的项目并将新项目添加到后面。如果字典的大小没有增加,则将项目从列表中的现有位置移动到列表的后面。最后,请注意内部列表保留键,而不是值。这是为了确保在超出列表容量时 O(1) 出队。
谷歌搜索五分钟后发现两个:
我不知道有任何这样的实现,但自己实现听起来并不难。由于字典没有任何固有的顺序,字典中的键或值类型都需要有一些属性来表示它插入字典的顺序。然后,在您覆盖该Add
方法时,它可以检查计数是否达到最大值。如果是这样,则查看现有的键值对以找到插入顺序属性最低的键值对,并将其替换为新的键值对。否则,照常插入新的键值对。
不久前,我在 C# 3.0 中编写了一个完整的循环缓冲区实现,并在CodePlex上发布了源代码。它遵循 BCL 设计指南,并从System.Collections
.
我相信它应该很容易适应使用 aDictionary<TKey, TValue>
作为支持集合而不是 a List<T>
。
这个怎么样:
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);
}
}
我通过 System.Data.Sqlite ( http://sqlite.phxsoftware.com/ ) 包装器使用 SQLite 数据库表实现了类似的功能。您可以将其存储在磁盘上或作为内存数据库。您可以选择是否具有唯一键并让数据库引擎为您处理索引。每个键甚至可以有多个值。
当您写入表时,检查您是否处于 100 条记录的限制,如果是,则在插入之前删除。如果要保留唯一键,SQLite 支持“插入或替换”命令。也许这不像自定义 IDictionary 派生那样优雅,但它很有效,很灵活,并且很容易跨线程共享。