繁体   English   中英

c#/.net 3.5 字典是如何实现的?

[英]How is the c#/.net 3.5 dictionary implemented?

我正在使用一个应用程序,该应用程序使用许多大型词典(最多 10^6 个元素),其大小事先未知(尽管在某些情况下我可以猜测)。 我想知道字典是如何实现的,即如果我不给出字典大小的初始估计,效果会有多糟糕。 它是否像 List 那样在内部使用(自增长)数组? 在这种情况下,让字典增长可能会在 LOH 上留下大量未引用的大型数组。

使用Reflector ,我发现以下内容: 字典将数据保存在结构数组中。 它会计算该数组中还剩下多少空位。 当您添加一个项目并且没有空的地方时,它会增加内部数组的大小(见下文)并将数据从旧数组复制到新数组。

因此,如果您知道会有很多条目,我建议您应该使用在其中设置初始大小的构造函数。

编辑:逻辑实际上非常有趣:有一个名为HashHelpers的内部类来查找素数。 为了加快速度,它还在一个静态数组中存储了一些素数,从 3 到 7199369(有些丢失了;原因见下文)。 当您提供容量时,它会从数组中找到下一个素数(相同或更大的值),并将其用作初始容量。 如果你给它一个比它的数组更大的数字,它会开始手动检查。

因此,如果没有任何内容作为容量传递给字典,则起始容量为 3。

一旦超出容量,它将当前容量乘以 2,然后使用辅助类查找下一个更大的素数。 这就是为什么在数组中并不是每个素数都需要的原因,因为素数“靠得太近”并不是真正需要的。

所以如果我们不传递初始值,我们会得到(我检查了内部数组):

  1. 3
  2. 7
  3. 17
  4. 37
  5. 71
  6. 163
  7. 353
  8. 761
  9. 1597
  10. 3371
  11. 7013
  12. 14591
  13. 30293
  14. 62851
  15. 130363
  16. 270371
  17. 560689
  18. 1162687
  19. 2411033
  20. 4999559

一旦我们传递了这个大小,下一步就落在内部数组之外,它将手动搜索更大的素数。 这会很慢。 您可以使用 7199369(数组中的最大值)进行初始化,或者考虑字典中的条目超过 500 万是否意味着您应该重新考虑您的设计。

MSDN说:“使用键检索值非常快,接近 O(1),因为 Dictionary 类是作为哈希表实现的。” 并进一步“通过重新分配内部阵列,根据需要自动增加容量”。

但是如果你给出一个初始估计,你会得到更少的重新分配。 如果您从一开始就拥有所有项目,则 LINQ 方法ToDictionary可能会很方便。

哈希表通常有一个叫做负载因子的东西,如果达到这个阈值,它会增加后备桶存储。 IIRC 默认值类似于 0.72。 如果你有完美的散列,这可以增加到 1.0。

此外,当哈希表需要更多桶时,必须重新哈希整个集合。

对我来说最好的方法是使用 .NET Reflector。

http://www.red-gate.com/products/reflector/

使用反汇编代码查看实现。

  • JSON 作为字典
{
 "Details": 
    { 
    "ApiKey": 50125
    }
}
  • 模型应包含类型为字典的属性。
public Dictionary<string, string> Details{ get; set; }
  • 实现数据类型为“KeyValue”的 foreach() 块
       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;
                       }
                   }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM