我正在使用一个应用程序,它使用了许多大型词典(最多10^6个元素),其大小事先不知道(尽管在某些情况下可以猜测)。我想知道字典是如何实现的,即如果我没有给出字典大小的初始估计,会产生怎样的影响。它是否内部使用类似于List的(自增长)数组?如果是这样,那么让字典增长可能会在LOH上留下许多大的未引用数组。
我正在使用一个应用程序,它使用了许多大型词典(最多10^6个元素),其大小事先不知道(尽管在某些情况下可以猜测)。我想知道字典是如何实现的,即如果我没有给出字典大小的初始估计,会产生怎样的影响。它是否内部使用类似于List的(自增长)数组?如果是这样,那么让字典增长可能会在LOH上留下许多大的未引用数组。
HashHelpers
用于查找素数。为了加快速度,它还在一个静态数组中存储了一些从3到7199369的质数(有些缺失;原因见下文)。当您提供容量时,它从数组中找到下一个素数(相同或更大的值),并将其用作初始容量。如果您给它比其数组中的数字更大的数字,它将开始手动检查。一旦我们超过了这个大小,下一步就会超出内部数组的范围,需要手动搜索更大的质数。这会非常缓慢。你可以用7199369(数组中的最大值)进行初始化,或者考虑一下在字典中拥有超过500万条目是否意味着你应该重新考虑你的设计。
MSDN说:“通过使用其键检索值非常快,接近O(1),因为Dictionary类实现为哈希表。”并进一步解释说:“容量会随着需要重新分配内部数组而自动增加。”
但是如果您给出初始估计值,您将获得更少的重新分配。如果您从一开始就拥有所有项目,则可以使用LINQ方法ToDictionary。
ToDictionary
并不会预先分配字典的大小 - 它只是一个接一个地添加元素,直到完成。如果您事先知道(或可以猜测)字典的大小,最好自己创建一个字典并逐个添加元素。 - Zac Faragher哈希表通常有一个称为负载因子的东西,如果达到该阈值,将增加后备桶存储。我记得默认值大约是0.72。如果您拥有完美的哈希,可以将其增加到1.0。
此外,当哈希表需要更多桶时,整个集合必须重新散列。
{
"Details":
{
"ApiKey": 50125
}
}
public Dictionary<string, string> Details{ get; set; }
foreach (KeyValuePair<string, string> dict in Details)
{
switch (dict.Key)
{
case nameof(settings.ApiKey):
int.TryParse(kv.Value, out int ApiKey);
settings.ApiKey=ApiKey;
break;
default:
break;
}
}