C#Dictionary:更快的访问速度,但更少的内存占用

C#Dictionary:更快的访问速度,但更少的内存占用,c#,performance,dictionary,C#,Performance,Dictionary,我想要一些关于以最小内存占用和最大访问性能存储和访问的最佳方法的建议 例如。 对于每种车型,我都要存储车型和名称 我有以下几点想法: 备选案文1: Dictionary<string, Dictionary<string, string>> values = new Dictionary<string, Dictionary<string, string>>(); Dictionary<string, string> list = ne

我想要一些关于以最小内存占用和最大访问性能存储和访问的最佳方法的建议

例如。 对于每种车型,我都要存储车型和名称

我有以下几点想法:

备选案文1:

Dictionary<string, Dictionary<string, string>> values = new Dictionary<string, Dictionary<string, string>>();
Dictionary<string, string> list = new Dictionary<string, string>();
list.Add("2001", "Jetta S");
list.Add("2002", "Jetta SE");
list.Add("2002", "Jetta LE");
values.Add("VolksWagen", list);
字典值=新字典();
字典列表=新字典();
添加(“2001年”、“捷达S”);
添加(“2002”、“捷达SE”);
添加(“2002年”、“捷达乐”);
添加(“大众”,列表);
备选案文2:

Dictionary<string, List<KeyValuePair<string, string>>> values2 = new Dictionary<string, List<KeyValuePair<string, string>>>();
<pre lang="xml">List<KeyValuePair<string, string>> list2 = new List<KeyValuePair<string, string>>();
list2.Add(new KeyValuePair<string, string>("2001", "Jetta S"));
list2.Add(new KeyValuePair<string, string>("2002", "Jetta SE"));
list2.Add(new KeyValuePair<string, string>("2002", "Jetta LE"));
values2.Add("VolksWagen", list2);
字典值2=新字典();
List list2=新列表();
列表2.添加(新的KeyValuePair(“2001”、“捷达S”);
列表2.添加(新的KeyValuePair(“2002”、“捷达SE”);
列表2.添加(新的KeyValuePair(“2002”、“捷达乐”);
价值2.添加(“大众”,列表2);
备选案文3:

Dictionary<string, List<string>> values1 = new Dictionary<string, List<string>>();
List<string> list1 = new List<string>();
list1.Add("2001:Jetta S");
list1.Add("2002:Jetta SE");
list1.Add("2002:Jetta LE");
values1.Add("VolksWagen", list1);
字典值1=新字典();
List list1=新列表();
清单1.添加(“2001年:捷达S”);
清单1.添加(“2002年:捷达SE”);
清单1.添加(“2002年:捷达乐”);
价值1.添加(“大众”,列表1);
  • 选项1:更快地访问make和 名称,但大多数内存占用
  • 选项2:快速访问make和 名称,但内存占用更多
  • 选项3:缓慢访问make和 名称(必须对其进行解析),但 更少的内存占用
这样的字典将超过1500本

您对最快的访问速度和更少的内存占用有什么建议吗

谢谢。

SortedList
是一个简单的列表(因此不会大幅增加内存占用),它使用二进制搜索进行访问-so
O(log(n))
-因此速度不如
O(1)
处的
字典
,但比
O(n)
处的
列表
(或其他线性搜索)要好得多

如果您想要最快的访问速度,您需要为哈希表使用额外的内存

作为旁注,
SortedList
还允许通过int-index进行有效访问,这对于
SortedDictionary
来说很难,对于
字典来说几乎毫无意义


显然,在您的场景中,您可能需要将
SortedList
与嵌套键或复合键相结合,但在我看来,这将是实现内存和访问器性能平衡的最佳途径。您可以使用专用复合键,即带有复合键成员的iummutable
struct
,覆盖
GetHashCode()
Equals
,实现
IEquatable
,对于排序:实现
IComparable
IComparable

您不应该主要根据内存“占用”来选择数据结构,而应该根据访问模式:您希望进行的最频繁的查找是什么,结构更新的频率是多少等等

如果您想填充结构一次,然后按制造和施工年份查找汽车,第一种方法似乎最合理(且可读/可理解)


顺便说一句,考虑到一年内可以发布多个模型,您可能应该使用
字典
。如果你真的想存储几年,你不应该使用字符串作为键,而应该使用
Int16

当谈到数据结构中的访问时,理解读访问和写访问之间的区别是很重要的。至于字典,如果我没有弄错的话,您将通过
时间获得
O(1)
访问
值的权限,但是
O(log(n))
写入时间。当使用普通列表时,总是要添加
O(1)
,但访问数据却是
O(n)
。至于内存占用,它几乎是一样的:
O(n)
在最坏的情况下

您需要存储/访问多少个值? 根据您的代码示例

备选案文1:不适当:

list.Add("2002", "Jetta SE");
list.Add("2002", "Jetta LE");
密钥必须是唯一的,所以

选项2:
字典

是您所需要的。

您可以将
字典
名称值集合
一起使用:

var values = new Dictionary<string, NameValueCollection>();
NameValueCollection list = new NameValueCollection();
list.Add("2001", "Jetta S");
list.Add("2002", "Jetta SE");
list.Add("2002", "Jetta LE");
values.Add("VolksWagen", list);
var values=newdictionary();
NameValueCollection列表=新的NameValueCollection();
添加(“2001年”、“捷达S”);
添加(“2002”、“捷达SE”);
添加(“2002年”、“捷达乐”);
添加(“大众”,列表);
或使用集合初始值设定项:

var values = new Dictionary<string, NameValueCollection> 
    { 
        { "VolksWagen", new NameValueCollection 
            { 
                { "2001", "Jetta S" }, 
                { "2002", "Jetta SE" }, 
                { "2002", "Jetta LE" } 
            } 
        } 
    };
var值=新字典
{ 
{“大众”,新名称ValueCollection
{ 
{“2001”,“捷达S”},
{“2002”,“捷达SE”},
{“2002”,“捷达乐”}
} 
} 
};

虽然我不是内存占用方面的专家,但这将为您提供此特定场景中的最佳访问模式。

“具有最小内存占用和最大访问性能。”-它们通常是相反的约束(时间与空间)选项1不会对重复键抛出异常吗?这些列表多久更新一次?我个人喜欢简单易读的代码,除非代码运行太慢,我不得不面对性能问题。我想每个人看到
List
都会觉得有点奇怪。我会建议创建一个结构来封装年份,并使性能与KeyValuePair相同,但代码的可读性要高得多。要添加的
O(1)
假设您在末尾添加;对于基于数组的列表(显然,对于链表更好)来说,insert可能会很昂贵。如果OP的目的是减少内存占用,那么平坦的
O(n)
可能是正确的,但没有帮助;对于实现A和B,A可能需要比B多5000倍的空间,但两者仍然是
O(n)
@Marc,我编辑了我的帖子,添加了“在最坏的情况下”。至于写入时间,如果保留最后一个索引,则insert不必花费太多,只要使用它即可。当然,我们应该在这里讨论再分配问题,但这与以下问题无关:)