这并不是对你问题的直接回答,但我有一个类可以提高集合Contains()方法的性能。我建立了一个Queue的子类,并添加了一个字典,将哈希码映射到对象列表。而Dictionary.Contains()函数的复杂度为O(1),而List.Contains()、Queue.Contains()和Stack.Contains()的复杂度为O(n)。
字典的值类型是一个包含具有相同哈希码的对象的队列。调用者可以提供实现IEqualityComparer的自定义类对象。您可以使用此模式来处理栈或列表。只需进行一些少量更改即可完成代码。
private class HashQueue<T> : Queue<T>
{
private readonly IEqualityComparer<T> _comp;
public readonly Dictionary<int, Queue<T>> _hashes;
public HashQueue(IEqualityComparer<T> comp = null) : base()
{
this._comp = comp;
this._hashes = new Dictionary<int, Queue<T>>();
}
public HashQueue(int capacity, IEqualityComparer<T> comp = null) : base(capacity)
{
this._comp = comp;
this._hashes = new Dictionary<int, Queue<T>>(capacity);
}
public HashQueue(IEnumerable<T> collection, IEqualityComparer<T> comp = null) : base(collection)
{
this._comp = comp;
this._hashes = new Dictionary<int, Queue<T>>(base.Count);
foreach (var item in collection)
{
this.EnqueueDictionary(item);
}
}
public new void Enqueue(T item)
{
base.Enqueue(item);
this.EnqueueDictionary(item);
}
private void EnqueueDictionary(T item)
{
int hash = this._comp == null ? item.GetHashCode() : this._comp.GetHashCode(item);
Queue<T> temp;
if (!this._hashes.TryGetValue(hash, out temp))
{
temp = new Queue<T>();
this._hashes.Add(hash, temp);
}
temp.Enqueue(item);
}
public new T Dequeue()
{
T result = base.Dequeue();
int hash = this._comp == null ? result.GetHashCode() : this._comp.GetHashCode(result);
Queue<T> temp;
if (this._hashes.TryGetValue(hash, out temp))
{
temp.Dequeue();
if (temp.Count == 0)
this._hashes.Remove(hash);
}
return result;
}
public new bool Contains(T item)
{
int hash = this._comp == null ? item.GetHashCode() : this._comp.GetHashCode(item);
return this._hashes.ContainsKey(hash);
}
public new void Clear()
{
foreach (var item in this._hashes.Values)
item.Clear();
this._hashes.Clear();
base.Clear();
}
}
我的简单测试表明,我的 HashQueue.Contains()
比 Queue.Contains()
运行速度更快。使用计数设置为 10,000 运行测试代码,HashQueue 版本需要 0.00045 秒,而 Queue 版本需要 0.37 秒。当计数为 100,000 时,HashQueue 版本需要 0.0031 秒,而 Queue 版本需要 36.38 秒!
以下是我的测试代码:
static void Main(string[] args)
{
int count = 10000;
{
var q = new HashQueue<int>(count);
for (int i = 0; i < count; i++)
q.Enqueue(i);
System.Diagnostics.Stopwatch sw = System.Diagnostics.Stopwatch.StartNew();
for (int i = 0; i < count; i++)
{
bool contains = q.Contains(i);
}
sw.Stop();
Console.WriteLine(string.Format("HashQueue, {0}", sw.Elapsed));
}
{
var q = new Queue<int>(count);
for (int i = 0; i < count; i++)
q.Enqueue(i);
System.Diagnostics.Stopwatch sw = System.Diagnostics.Stopwatch.StartNew();
for (int i = 0; i < count; i++)
{
bool contains = q.Contains(i);
}
sw.Stop();
Console.WriteLine(string.Format("Queue, {0}", sw.Elapsed));
}
Console.ReadLine();
}