Answers:
两个重大区别:
Lookup
是一成不变的。是的:)(至少,我相信具体的Lookup
类是不可变的,并且该ILookup
接口不提供任何可变成员。当然,可能还有其他可变的实现。)KeyNotFoundException
。(因此,没有TryGetValue
AFAICR。)它们的效率很可能相当-例如,查找可能会Dictionary<TKey, GroupingImplementation<TValue>>
在幕后使用。根据您的要求在它们之间进行选择。我个人发现查找通常比a更合适Dictionary<TKey, List<TValue>>
,主要是因为上面的前两点。
注意,作为一个实现细节,的具体实现IGrouping<,>
,其用于值工具IList<TValue>
,这意味着它是有效的与使用Count()
,ElementAt()
等等。
有趣的是,没有人说出实际最大的差异(直接来自MSDN):
查找类似于字典。区别在于字典将键映射到单个值,而查阅将键映射到值的集合。
a Dictionary<Key, List<Value>>
和Lookup<Key, Value>
逻辑上都可以保存以相似方式组织的数据,并且两者的效率顺序相同。主要区别是a Lookup
是不可变的:它没有Add()
方法,也没有公共构造函数(并且正如Jon所述,您可以无例外地查询不存在的键并将该键作为分组的一部分)。
至于使用哪个,实际上取决于您要使用它们的方式。如果您要维护一个不断变化的键到多个值的映射,则a Dictionary<Key, List<Value>>
可能更好,因为它是可变的。
但是,如果您有一系列数据,并且只想要按键组织的数据的只读视图,则查找非常容易构造,并且将为您提供只读快照。
an ILookup<K,V>
和a 之间的主要区别Dictionary<K, List<V>>
是字典是可变的;您可以添加或删除键,也可以从查找的列表中添加或删除项。an ILookup
是不可变的,一旦创建便无法修改。
这两种机制的基本实现将相同或相似,因此它们的搜索速度和内存占用量将大致相同。
如果您试图使结构像a一样有效,Dictionary
但是您不确定输入中没有重复的键,那么这样做Lookup
会更安全。
如另一个答案中所述,它还支持空键,并且在查询任意数据时始终返回有效结果,因此它对于未知输入更具弹性(不像Dictionary那样容易引发异常)。
如果将它与System.Linq.Enumerable.ToDictionary
函数进行比较,则尤其如此:
// won't throw
new[] { 1, 1 }.ToLookup(x => x);
// System.ArgumentException: An item with the same key has already been added.
new[] { 1, 1 }.ToDictionary(x => x);
另一种方法是在foreach
循环中编写您自己的重复密钥管理代码。
如果您不需要列表,并且要管理大量项目,那么Dictionary
(甚至您自己定制的定制结构)将更加高效:
Stopwatch stopwatch = new Stopwatch();
var list = new List<string>();
for (int i = 0; i < 5000000; ++i)
{
list.Add(i.ToString());
}
stopwatch.Start();
var lookup = list.ToLookup(x => x);
stopwatch.Stop();
Console.WriteLine("Creation: " + stopwatch.Elapsed);
// ... Same but for ToDictionary
var lookup = list.ToDictionary(x => x);
// ...
由于Lookup
必须维护每个键的项目列表,因此它比字典慢(对于大量项目,大约慢3倍)
查找速度:创建:00:00:01.5760444
词典速度:创建:00:00:00.4418833