LINQ ToDictionary初始容量

时间:2012-05-29 14:39:12

标签: c# .net linq extension-methods

我经常使用LINQ扩展方法ToDictionary,但我对这个性能感到疑惑。没有参数来定义字典的容量,并且列表中包含100k或更多项,这可能会成为一个问题:

IList<int> list = new List<int> { 1, 2, ... , 1000000 };
IDictionary<int, string> dictionary = list.ToDictionary<int, string>(x => x, x => x.ToString("D7"));

实现是否实际采用list.Count并将其传递给字典的构造函数? 或者是否足够快地调整字典的大小,所以我真的不必担心它?

5 个答案:

答案 0 :(得分:2)

  

实现是否实际采用list.Count并将其传递给字典的构造函数?

这是一个实施细节,对你来说无关紧要。

  

或者是否足够快地调整字典的大小,所以我真的不必担心它?

嗯,我不知道。只有您知道这是否实际上是您的应用程序的瓶颈,以及性能是否可以接受。如果你想知道它是否足够快,请编写代码并计时。正如Eric Lippert所说的那样,如果你想知道两匹马的速度有多快,你是否会在相互竞争中陷入困境,或者你是否要求互联网上的随机陌生人哪一匹更快?

那就是说,我很难将这成为任何实际应用中的瓶颈。如果在字典中添加项目是应用程序的瓶颈,那么你做错了。

答案 1 :(得分:2)

  

实现是否实际采用list.Count并将其传递给   字典的构造函数?

没有。根据{{​​3}},实施基本上是这样的:

Dictionary<TKey, TElement> dictionary = new Dictionary<TKey, TElement>(comparer);
foreach (TSource current in source)
{
    dictionary.Add(keySelector(current), elementSelector(current));
}
return dictionary;

如果您配置文件您的代码并确定ToDictionary操作是您的瓶颈,那么基于上述代码制作您自己的功能是微不足道的。

答案 2 :(得分:0)

我不知道调整字典的大小,但是用dotPeek.exe检查实现表明实现不会占用列表长度。

代码的基本功能是:

  • 创建新词典
  • 迭代序列并添加项目

如果你发现这是一个瓶颈,那么创建你自己的扩展方法ToDictionaryWithCapacity就可以轻而易举,这种扩展方法适用于可以实际计算其长度而不需要迭代整个事物的东西。

刚刚扫描了Dictionary实施。基本上,当它开始填满时,内部列表通过将其大致加倍到接近素数来调整大小。所以这不应该太频繁发生。

答案 3 :(得分:0)

我认为这不会成为TBH的瓶颈。如果您有真正的抱怨和问题,那么您应该在那时查看它是否可以改进它,可能是您可以进行分页而不是一次转换所有内容。

答案 4 :(得分:0)

  

实现是否实际采用list.Count并将其传递给字典的构造函数?

没有。那是因为调用Count()将枚举源,然后将其添加到字典中将第二次枚举源。枚举源两次并不是一个好主意,例如,这会在DataReaders上失败。

  

或者是否足够快地调整字典的大小,所以我真的不必担心它?

Dictionary.Resize方法用于扩展字典。它分配一个新字典并将现有项复制到新字典中(使用Array.Copy)。字典大小以素数步长增加。

这不是最快的方法,但如果你不知道它的大小就足够快。