有时我们希望复用一个Dictionary的时候,可以Clear()也可以,直接new一个新的对象,
两者到底是哪个划算呢?
我们看程序:
private void Experiment()
{
System.Diagnostics.Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
//Dictionary<int, int> aa = new Dictionary<int, int>();
for (var loop = 0; loop < 30000; loop++)
{
Dictionary<int, int> aa = new Dictionary<int, int>();
for (var i = 0; i < 10000; i++)
{ aa.Add(i,i); }
//aa.Clear();
}
stopwatch.Stop();
Console.WriteLine("All timeL:"+stopwatch.Elapsed.TotalSeconds);
}
数据结果如下:
使用Clear()时间为6秒。而使用new object的方法,时间为20秒,我觉得只所以这样
是因为NEW object的方案中,需要执行很多次Resize的操作。
这些东西看基类代码如下:
Add操作如下:
public void Add(TKey key, TValue value)
{
this.Insert(key, value, true);
}
其调用Insert操作,代码如下:
private void Insert(TKey key, TValue value, bool add)
{
int freeList;
if (key == null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
}
if (this.buckets == null)
{
this.Initialize(0);
}
int num = this.comparer.GetHashCode(key) & 0x7fffffff;
int index = num % this.buckets.Length;
for (int i = this.buckets[index]; i >= 0; i = this.entries[i].next)
{
if ((this.entries[i].hashCode == num) && this.comparer.Equals(this.entries[i].key, key))
{
if (add)
{
ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_AddingDuplicate);
}
this.entries[i].value = value;
this.version++;
return;
}
}
if (this.freeCount > 0)
{
freeList = this.freeList;
this.freeList = this.entries[freeList].next;
this.freeCount--;
}
else//散列已满
{
if (this.count == this.entries.Length)
{
this.Resize();//为散列重新开辟一块儿内存空间
index = num % this.buckets.Length;
}
freeList = this.count;
this.count++;
}
this.entries[freeList].hashCode = num;
this.entries[freeList].next = this.buckets[index];
this.entries[freeList].key = key;
this.entries[freeList].value = value;
this.buckets[index] = freeList;
this.version++;
}
Resize()如下:
private void Resize()
{
int prime = HashHelpers.GetPrime(this.count * 2);
int[] numArray = new int[prime];//开辟新的数组
for (int i = 0; i < numArray.Length; i++)
{
numArray[i] = -1;
}
Entry<TKey, TValue>[] destinationArray = new Entry<TKey, TValue>[prime];//开辟新的数组
Array.Copy(this.entries, 0, destinationArray, 0, this.count);
for (int j = 0; j < this.count; j++)
{
int index = destinationArray[j].hashCode % prime;
destinationArray[j].next = numArray[index];
numArray[index] = j;
}
this.buckets = numArray;
this.entries = destinationArray;
}