Bu tam olarak sorunuzun cevabı değil, ancak Contains () 'in bir koleksiyondaki performansını artıran bir sınıfım var. Bir Kuyruğun alt sınıfını oluşturdum ve hashcode'ları nesne listelerine eşleyen bir Sözlük ekledim. Dictionary.Contains()
İşlev O (1), oysa olduğu List.Contains()
, Queue.Contains()
ve Stack.Contains()
O (n) 'dir.
Sözlüğün değer türü, aynı hashcode ile nesneleri tutan bir kuyruktur. Çağıran, IEqualityComparer uygulayan özel bir sınıf nesnesi sağlayabilir. Bu kalıbı Yığınlar veya Listeler için kullanabilirsiniz. Kodun yalnızca birkaç değişikliğe ihtiyacı olacaktır.
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();
}
}
Basit testlerim, HashQueue.Contains()
daha hızlı çalıştığımı gösteriyor Queue.Contains()
. Test kodunu sayım 10.000 olarak ayarlanmış olarak çalıştırmak, HashQueue sürümü için 0.00045 saniye ve Kuyruk sürümü için 0.37 saniye sürer. 100.000 sayımla HashQueue sürümü 0.0031 saniye, Kuyruk ise 36.38 saniye sürüyor!
İşte test kodum:
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();
}