我在SortedDictionary<string, MyClass>
我做了以下事情并花了很多年,有什么想法吗?
for(int i = 0; i<dic.Count-1; i++)
{
Debug.WriteLine(dic.ElementAt(i).Value.ToString());
}
答案 0 :(得分:4)
SortedDictionary<TKey, TValue>
类不直接支持(快速)索引检索;它在内部实现为二叉搜索树。因此,每次调用LINQ Enumerable.ElementAt
方法都会创建一个新的枚举器,它从头开始迭代集合中键值对(按键排序)表示的序列的每个值。 直到达到所需的索引。这意味着循环必须在它完成之前拉出类似1 + 2 + 3 + ... + Count
(大约2万亿)的元素,使其(至少)时间复杂度呈二次方。
试试这个,它应该在大致线性的时间内运行:
foreach(var myClass in dic.Values)
Debug.WriteLine(myClass);
如果您确实希望通过索引快速访问(从提供的代码中,似乎没有任何理由表明这一点),请考虑使用SortedList<TKey, TValue>
。这个选择存在缺点(较慢的非附加插入和删除),你应该评估。
我还注意到循环条件是i < dic.Count - 1
而不是更常见的i < dic.Count
。这可能是一个错误的错误,或者您打算不考虑字典中的最后一个值。在后一种情况下,您可以维护一个局部变量作为计数器,或使用LINQ:
foreach(var myClass in dic.Values.Take(dic.Count - 1))
Debug.WriteLine(myClass);
答案 1 :(得分:2)
foreach
可能会更快,因为您不使用索引器
foreach (var value in dic.Values)
Debug.Writeline(value)
另外,就速度而言,Debug.Writeline
可能不是最佳选择(无论如何你要做200万个调试跟踪条目?)。考虑写入文件,数据库等
编辑查看反射器,在SortedDictionry中查找值可归结为二分搜索:
internal virtual Node<T> FindNode(T item)
{
int num;
for (Node<T> node = this.root; node != null; node = (num < 0) ? node.Left : node.Right)
{
num = this.comparer.Compare(item, node.Item);
if (num == 0)
{
return node;
}
}
return null;
}
SortedDictionary迭代的实现似乎更复杂:
public bool MoveNext()
{
this.tree.VersionCheck();
if (this.version != this.tree.version)
{
ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
}
if (this.stack.Count == 0)
{
this.current = null;
return false;
}
this.current = this.stack.Pop();
SortedSet<T>.Node item = this.reverse ? this.current.Left : this.current.Right;
SortedSet<T>.Node node2 = null;
SortedSet<T>.Node node3 = null;
while (item != null)
{
node2 = this.reverse ? item.Right : item.Left;
node3 = this.reverse ? item.Left : item.Right;
if (this.tree.IsWithinRange(item.Item))
{
this.stack.Push(item);
item = node2;
}
else
{
if ((node3 == null) || !this.tree.IsWithinRange(node3.Item))
{
item = node2;
continue;
}
item = node3;
}
}
return true;
}
它似乎维护一个堆栈,其顶部元素是最小的(或最大的,取决于方向)one,因此始终是在迭代期间弹出和返回的堆栈。我没有进行任何复杂性分析,但每次运行二进制搜索时效率要高得多。
答案 2 :(得分:0)
使用foreach
:
foreach (var pair in d)
Debug.WriteLine(pair.Value);
我敢打赌,调试输出比字典查找需要更多时间。