Lookup()和Dictionary(列表()之间的区别)

时间:2012-11-13 14:28:21

标签: c# .net vb.net linq

我试图围绕哪些数据结构最有效以及何时/何地使用哪些数据结构。

现在,我可能只是对结构不够了解,但ILookup(of key, ...)Dictionary(of key, list(of ...))有什么不同?

另外,我想在哪里使用ILookup,哪里在程序速度/内存/数据访问等方面更有效?

6 个答案:

答案 0 :(得分:222)

两个显着差异:

  • Lookup是不可变的。是的:)(至少,我相信具体的Lookup类是不可变的,ILookup接口不提供任何变异成员。可能是其他可变实现,当然。)
  • 当您查找查找中不存在的键时,将返回空序列而不是KeyNotFoundException。 (因此没有TryGetValue,AFAICR。)

它们可能在效率方面相当 - 例如,查找可能会在幕后使用Dictionary<TKey, GroupingImplementation<TValue>>。根据您的要求在它们之间进行选择。我个人认为查找通常比Dictionary<TKey, List<TValue>>更合适,主要是由于上面的前两点。

请注意,作为实现细节,用于值的IGrouping<,>的具体实现实现IList<TValue>,这意味着它与Count(),{{1}一起使用效率很高。等等。

答案 1 :(得分:33)

有趣的是,没有人说出实际的最大差异(直接来自MSDN):

  

查找类似于词典。该   区别在于Dictionary将键映射到单个   值,而Lookup将键映射到集合   值。

答案 2 :(得分:31)

Dictionary<Key, List<Value>>Lookup<Key, Value>逻辑上都可以保存以类似方式组织的数据,两者的效率顺序相同。主要的区别是Lookup是不可变的:它没有Add()方法,也没有公共构造函数(正如Jon提到的那样,你可以查询一个没有异常的不存在的密钥,并将密钥作为分组)。

至于你使用哪种,它实际上取决于你想要如何使用它们。如果要维护一个不断修改的多个值的键映射,那么Dictionary<Key, List<Value>>可能更好,因为它是可变的。

但是,如果您有一系列数据并且只想要按键组织的数据的只读视图,那么查找很容易构建,并且会为您提供只读快照。

答案 3 :(得分:11)

ILookup<K,V>Dictionary<K, List<V>>之间的主要区别在于字典是可变的;您可以添加或删除密钥,还可以在查找的列表中添加或删除项目。 ILookup不可变的,一旦创建就无法修改。

这两种机制的底层实现将是相同或相似的,因此它们的搜索速度和内存占用量将大致相同。

答案 4 :(得分:9)

尚未提及的另一个区别是Lookup()supports null keys

  

Lookup类实现了ILookup接口。 Lookup非常类似于字典,除了允许多个值映射到同一个键,并且支持null键。

答案 5 :(得分:4)

如果不能选择例外,请转到查找

如果您尝试使结构与Dictionary一样高效,但您不确定输入中没有重复键,Lookup更安全。

正如另一个答案中所提到的,它也支持null键,并且在使用任意数据查询时返回总是有效的结果,因此它看起来对未知输入更具弹性(比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必须维护每个键的项目列表,因此它比Dictionary更慢(对于大量项目,大约慢3倍)

  

查询速度:   创作时间:00:00:01.5760444

     

字典速度:   创作时间:00:00:00.4418833