1

我经常使用 LINQ 扩展方法 ToDictionary,但我想知道性能。没有参数来定义字典的容量,并且列表包含 10 万个或更多项目,这可能会成为一个问题:

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 并将其传递给字典的构造函数?或者字典的大小调整是否足够快,所以我真的不用担心?

4

5 回答 5

2

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

不,根据ILSpy,实现基本上是这样的:

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

如果您分析您的代码并确定该ToDictionary操作是您的瓶颈,那么根据上述代码制作您自己的函数是微不足道的。

于 2012-05-29T14:51:20.197 回答
2

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

这是一个实现细节,对您来说应该无关紧要。

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

嗯,我不知道。只有您知道这是否真的是您的应用程序的瓶颈,以及性能是否可以接受。如果您想知道它是否足够快,请编写代码并计时。正如 Eric Lippert 常说的那样,如果你想知道两匹马的速度,你是让它们相互竞争,还是你在互联网上随便问一个陌生人哪一匹更快?

也就是说,我很难想象这是任何实际应用程序中的瓶颈。如果将项目添加到字典是您的应用程序的瓶颈,那么您做错了什么。

于 2012-05-29T14:43:18.657 回答
0

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

代码的基本作用是:

  • 创建一个新字典
  • 迭代序列并添加项目

如果您发现这是一个瓶颈,那么创建自己的扩展方法将是微不足道的,该方法ToDictionaryWithCapacity可以在无需迭代整个事物的情况下实际计算其长度的事物上工作。

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

于 2012-05-29T14:45:16.817 回答
0

我认为这不会成为 TBH 的瓶颈。如果你有真正的抱怨和问题,你应该在那个时候查看它,看看你是否可以改进它,也许你可以做分页而不是一次转换所有东西。

于 2012-05-29T14:47:09.297 回答
0

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

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

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

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

这不是最快的方法,但如果您不知道大小,则足够快。

于 2012-05-29T14:59:25.070 回答