这不是一个真正的问题,因为我已经找到了答案,但仍然很有趣。
我一直认为哈希表是最快的关联容器,如果你正确地进行哈希的话。
然而,下面的代码非常慢。它只执行了大约100万次迭代,在Core 2 CPU上需要超过2分钟的时间。
该代码执行以下操作:它维护了集合todo
,其中包含它需要处理的项。在每次迭代中,它从此集合中取出一个项(无论哪个项),删除它,如果它还没有被处理就处理它(可能添加更多要处理的项),并重复此操作,直到没有要处理的项为止。
罪魁祸首似乎是Dictionary.Keys.First()操作。
问题是为什么它会这么慢?
Stopwatch watch = new Stopwatch();
watch.Start();
HashSet<int> processed = new HashSet<int>();
Dictionary<int, int> todo = new Dictionary<int, int>();
todo.Add(1, 1);
int iterations = 0;
int limit = 500000;
while (todo.Count > 0)
{
iterations++;
var key = todo.Keys.First();
var value = todo[key];
todo.Remove(key);
if (!processed.Contains(key))
{
processed.Add(key);
// process item here
if (key < limit) { todo[key + 13] = value + 1; todo[key + 7] = value + 1; }
// doesn't matter much how
}
}
Console.WriteLine("Iterations: {0}; Time: {1}.", iterations, watch.Elapsed);
这会导致:
Iterations: 923007; Time: 00:02:09.8414388.
将Dictionary更改为SortedDictionary即可:
Iterations: 499976; Time: 00:00:00.4451514.
使用2倍少的迭代次数,速度提高了300倍。
在Java中也是如此。
使用HashMap
代替Dictionary
,使用keySet().iterator().next()
代替Keys.First()
。