Dictionary 如何";“帮助”;具有业务逻辑知识的字典性能

Dictionary 如何";“帮助”;具有业务逻辑知识的字典性能,dictionary,data-structures,Dictionary,Data Structures,假设我有一本字典(在.NET中),键从1到100。 我从我的历史数据中知道,比如说,99%的时间我访问这本词典来检索键5、37、88的数据。 有没有一种方法可以让我组织这本词典,使它在使用这3个键时速度非常快,即使在寻找其余97个键时浪费了更多的时间? 或者,是否有一种不同的数据结构可以利用这些知识来提高数据访问的平均时间?在词典的合理实现中,查找的成本将主要由内存访问的成本决定。您的硬件将为您进行优化,将最频繁访问的项保留在最快的缓存级别中。除非你有一台微型计算机,否则100件物品将放在你最快

假设我有一本字典(在.NET中),键从1到100。 我从我的历史数据中知道,比如说,99%的时间我访问这本词典来检索键5、37、88的数据。 有没有一种方法可以让我组织这本词典,使它在使用这3个键时速度非常快,即使在寻找其余97个键时浪费了更多的时间?
或者,是否有一种不同的数据结构可以利用这些知识来提高数据访问的平均时间?

在词典的合理实现中,查找的成本将主要由内存访问的成本决定。您的硬件将为您进行优化,将最频繁访问的项保留在最快的缓存级别中。除非你有一台微型计算机,否则100件物品将放在你最快的缓存中

也就是说,如果使用具有单独链接的哈希表,则可以将这些项移动到其链的前面。这确保了在最坏的情况下查找这些项是O(1),而对于字典中的至少一个项,查找概率很高,为O(logn/logn)


当然,如果您只有100个键,使用哈希表而不是字典将确保每个键都有O(1)个最坏情况访问。

您可以在字典前面使用一个小缓存,这可能会更快。例如,如果您知道大多数访问权限都是针对项目3、37和88的,那么您可以:

private Dictionary<int, MyDataType> TheDictionary;
private KeyValuePair<int, MyDataType>[] quickLookup;

void InitializeDictionary()
{
    TheDictionary = new Dictionary<int, MyDataType>();
    // here, initialize the dictionary with the data.

    // Now, set up the cache
    quickLookup = new KeyValuePair<int, MyDataType>[]
    {
        new KeyValuePair(3, TheDictionary[3]),
        new KeyValuePair(37, TheDictionary[37]),
        new KeyValuePair(88, TheDictionary[88])
    };
如果您的缓存只有三个项目,那么这将给您一个小的性能提升。但是,如果您得到的条目超过五到六个,那么它的性能可能会比直接查找字典的性能差。你必须做一些计时来确定最佳点在哪里

还要注意的是,如果你真的对这种微优化感兴趣,你可能应该用一个
for
循环来代替
foreach

for (int i = 0; i < quickLookup.Length)
{
    if (quickLookup[i].Key == key)
    ...
    ...
for(int i=0;i
这将消除创建枚举器的开销

这种技术应该提供性能提升的原因是访问字典需要从密钥计算哈希。虽然这是一种快速操作,但它的开销仍然比几个数组访问要大。同样,在将其投入生产之前,您需要使用代表性数据对其进行彻底测试和分析

C#编译器在为
switch
语句生成代码时使用类似的方法(至少过去使用过;我有一段时间没有检查过)。如果
switch
包含的案例数少于一些(上次检查时,我想是六个),然后编译器生成一系列
if/else
语句。对于六个或更多项,它生成键和分支位置的字典,并编写代码在字典中查找大小写值并分支到相关代码

for (int i = 0; i < quickLookup.Length)
{
    if (quickLookup[i].Key == key)
    ...
    ...