集合类型的初始容量,例如字典和列表

问题描述 投票:0回答:5

.NET 中的某些集合类型具有可选的“初始容量”构造函数参数。 例如:

Dictionary<string, string> something = new Dictionary<string,string>(20);

List<string> anything = new List<string>(50);

我似乎无法在 MSDN 上找到这些对象的默认初始容量。

如果我知道我只会在字典中存储 12 个左右的项目,那么将初始容量设置为 20 之类的值是否有意义?

我的推理是,假设容量像 StringBuilder 一样增长,每次容量达到时都会加倍,并且每次重新分配的成本都很高,为什么不将大小预设为您知道将保存数据的大小,并留出一些额外的空间万一? 如果初始容量是 100,并且我知道我只需要十几个左右,那么似乎其余的内存都没有分配。

c# .net memory-management collections object-initializers
5个回答
88
投票

如果未记录默认值,原因可能是最佳初始容量是一个“实现细节”,并且可能会在框架版本之间发生变化。也就是说,您不应该编写假定某个默认值的代码。 构造函数

重载容量适用于您比类更了解

预期项目数量的情况。例如,如果您创建一个包含 50 个值的集合,并且知道该数字永远不会增加,则可以使用 50 的容量来初始化该集合,因此如果默认容量较低,则无需调整大小。 也就是说,您可以使用 Reflector 确定默认值。例如,在 .NET 4.0(可能还有以前的版本)中,

    List
  • 初始化为容量 0。当添加第一个项目时,它会重新初始化为容量 4。随后,每当达到容量时,容量就会加倍。

  • 字典
  • 也被初始化为容量0。但它使用了完全不同的算法来增加容量:它总是将容量增加到素数。


13
投票
主要

担心这一点,因为这样可以避免分配、复制和收集多个数组。 大多数收藏确实使用了加倍策略。


9
投票
List<T>

Dictionary<TKey, TValue>
的默认容量都是0。
    


3
投票

例如,

这里有一些示例代码和基准测试

我尝试过。 我在我的机器上运行了代码并得到了类似的结果。

也就是说,当指定了初始大小时,它不会提高 ConcurrentDictionary 添加对象时的速度。从技术上讲,我认为它

应该

,因为它不需要花费时间或资源来调整自身大小。 是的,它的运行速度可能不如普通字典,但我仍然希望设置了初始大小的 ConcurrentDictionary 比没有设置初始大小的 ConcurrentDictionary 具有一致、更快的性能,尤其是当人们知道提前要添加到其中的项目数量。

所以这个故事的寓意是设置初始大小并不总是能保证性能的提高。


-1
投票
new List[<].*[>][(\(\))?[ ]+[{]

Ctrl
+Shift+F 并启用正则表达式选项来搜索您可能需要为其添加初始容量的所有列表;-)

© www.soinside.com 2019 - 2024. All rights reserved.