[英]How would I implement a Queue of type Dictionary<int, string> and iterate/enqueue/dequeue in C#
[英]How would I implement a QueueDictionary, a combination of Queue and Dictionary in C#?
基本上我想要的数据结构将镜像MSMQ,但会在内存中,因为它在一个进程中使用。 通过镜像MSMQ,我的意思是你会将对象排队,然后你可以将对象出列或使用密钥检索它们。 这是我最初的尝试。 这个尝试的主要问题是Get by id会频繁使用,因此队列最终会有很多“死”对象。
public class QueueDictionary<TKey, TValue>
{
private readonly Queue _queue = new Queue();
private readonly Dictionary<TKey, TValue> _dictionary = new Dictionary<TKey, TValue>();
private readonly object _syncRoot = new object();
public TValue Dequeue()
{
lock (_syncRoot)
{
TKey key = (TKey)_queue.Dequeue();
while (!_dictionary.ContainsKey(key))
key = (TKey)_queue.Dequeue();
return _dictionary[key];
}
}
public TValue Get(TKey key)
{
lock (_syncRoot)
{
TValue result = _dictionary[key];
_dictionary.Remove(key);
return result;
}
}
public void Enqueue(TKey key, TValue value)
{
lock (_syncRoot)
{
_dictionary.Add(key, value);
_queue.Enqueue(key);
}
}
}
您可以使用LinkedList,而不是在内部使用Queue。 然后在Dictionary中,您可以存储Key和LinkedListNode。 然后,当您从字典中删除该项时,您可以取消链接列表中的LinkedListNode链接。 当然,你放弃了队列的局部性,但获得了随机访问的性能。
这是一个快速而肮脏的例子,没有经过测试,因此可以解释任何错误和错误检查。 例如,您应检查队列是否为空,确保具有相同键的项目尚未在字典中等。
public class QueueDictionary<TKey, TValue>
{
private readonly LinkedList<Tuple<TKey, TValue>> _queue =
new LinkedList<Tuple<TKey, TValue>>();
private readonly Dictionary<TKey, LinkedListNode<Tuple<TKey, TValue>>>
_dictionary = new Dictionary<TKey, LinkedListNode<Tuple<TKey, TValue>>>();
private readonly object _syncRoot = new object();
public TValue Dequeue()
{
lock (_syncRoot)
{
Tuple<TKey, TValue> item = _queue.First();
_queue.RemoveFirst();
_dictionary.Remove(item.Item1);
return item.Item2;
}
}
public TValue Dequeue(TKey key)
{
lock (_syncRoot)
{
LinkedListNode<Tuple<TKey, TValue>> node = _dictionary[key];
_dictionary.Remove(key);
_queue.Remove(node);
return node.Value.Item2;
}
}
public void Enqueue(TKey key, TValue value)
{
lock (_syncRoot)
{
LinkedListNode<Tuple<TKey, TValue>> node =
_queue.AddLast(new Tuple<TKey, TValue>(key, value));
_dictionary.Add(key, node);
}
}
}
那么你的对象可以像队列实际上并没有使用Queue类作为它的内部存储。 根据您计划保留的项目数量,可能更容易维护单个LinkedList(T),而不是将项目存储在LinkedList(T)和Dictionary(K,V)中。
但基本上,您可以使用LinkedList(T)而不是在内部使用Queue,只需将新项添加到列表的末尾,然后从列表的前面出列。 当你需要通过键找到一个时,你可以只扫描列表中的匹配键,或者如果项目数量使这个表现不佳,你可以用一个字典(K,LinkedListNode(T))加倍你的存储并使用密钥查找的字典。
如果您使用双链表作为队列,那么您可以完全控制Enqueue,Dequeue,特别是Get方法。 因此,在Get方法中,您只需从双链表中删除键即可。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.