【问题标题】:Where can I learn about the various types of .NET lists?在哪里可以了解各种类型的 .NET 列表?
【发布时间】:2010-09-16 22:03:31
【问题描述】:

有没有人知道一个很好的资源来简明地解释 C# 中可用的不同类型的列表以及何时适合使用它们?

例如,列表、哈希表、字典等

我不太确定什么时候应该使用什么。

【问题讨论】:

    标签: .net collections


    【解决方案1】:

    尽管它们都是集合,但它们并不都是列表。这是一个简短的摘要。

    非泛型集合(API 以object 表示。值类型被装箱。

    这些大多在System.Collections 命名空间中:

    • ArrayList:由数组支持的项目列表。快速随机读/写访问。快速添加到尾部,如果缓冲区不需要调整大小。
    • Hashtable:从键映射到值。键是唯一的,值不必是唯一的。使用 GetHashCode 方法来实现接近 O(1) 的读/写访问(除了所有项目具有相同哈希或后备存储需要重建的恶劣情况)。遍历键/值对会产生不可预测的顺序。 (嗯,实际上是不可预测的。)
    • SortedList: 就像一个 Hashtable,但条目总是按 key 排序的顺序返回。存储为键/值对列表。
    • Stack: 后进先出集合
    • Queue:先进先出集合
    • Array:固定大小 O(1) 随机访问;非泛型,但也有强类型形式

    通用集合。 (强类型 API,不会将值类型装箱(假设合适的 T)。

    这些大多在System.Collections.Generic namespace:

    可能最重要的集合接口IEnumerable(和IEnumerable<T>)。这表示一个项目序列,就像 Stream 表示一个字节序列一样。没有随机访问,只有前向阅读。 LINQ to Objects 就是基于此,几乎所有的集合类型都实现了它。

    【讨论】:

    • 还有 System.Collections.Specialized 有更多好东西——比如 StringDictionary 和 NameValueCollection
    • @Hafthor:是的,尽管其中大多数已经被泛型所淘汰。
    • 非常好的列表 你已经组装好了。我用过的东西都在里面。
    【解决方案2】:

    为了解释 tobsen 之前的回答,C5 通用集合库有大量的集合。我将在这里描述其中的一些:

    队列/堆栈

    • CircularQueue&lt;T&gt;:此类提供严格的队列和堆栈功能。同样,使用索引器可以有效O(1) 访问堆栈/队列中的任何项目:cq[0](其中 0 是最旧的项目,接下来要出列,最后要弹出)。

    列表

    注意:ArrayListLinkedList 也可以用作队列/堆栈

    • ArrayList&lt;T&gt;:与 System.Collections.Generic (SCG)List&lt;T&gt; 中的对应项类似,它由数组支持,保证 O(1) 索引,但最坏情况 O (n) 插入。O(n) 查找项目。
    • LinkedList&lt;T&gt;:与对应的 SCG.LinkedList&lt;T&gt; 类似。使用双向链表,保证 O(1) 插入,但最坏情况 O(n) 索引(在实践中,是成比例的距离列表的头部或尾部)。还 O(n) 来查找项目。排序使用稳定的合并排序。
    • HashedArrayList&lt;T&gt;:类似于上面的ArrayList&lt;T&gt;,但不允许重复。您获得的回报是查找项目及其索引的时间减少到 O(1)。
    • HashedLinkedList&lt;T&gt;:类似于上面的LinkedList&lt;T&gt;,但不允许重复。和以前一样,找到一个项目的时间减少到 O(1),但找到它的索引的时间仍然是 O(n)。
    • WrappedArray&lt;T&gt;:与ArrayList&lt;T&gt; 非常相似,它充当实现C5.IList&lt;T&gt; 的数组的包装器,但如果尝试修改集合则抛出异常(IsFixedSize 为真,Add,@但是,987654339@、Insert 不起作用;SortShuffleReverse 可以,因为它们是就地操作)。

    列表还提供“查看”功能,它表示底层列表的一部分,允许执行本地操作。使用 C5 书中提供的模式,可以使用对数组和链表都有效的视图来执行操作。任何列表操作也可以在视图上执行,将它们的效果限制在底层列表的子集中。

    排序集合

    • SortedArray&lt;T&gt;:类似于ArrayList&lt;T&gt;,除了它保持其项目排序并且不允许重复。请注意,此集合上的随机插入和删除速度很慢。如果项目数量很少或很少修改但经常通过项目索引或值访问,则此集合是最佳选择。
    • TreeSet&lt;T&gt;:使用红黑树结构来保持项目排序。作为一个集合,它不允许重复。按索引或项值访问以及插入/删除需要 O(log n)。
    • TreeBag&lt;T&gt;:使用红黑树,保持项目排序。作为一个包,它确实允许重复,但不会在树中存储重复,而是通过计数来保持重复。

    TreeSet&lt;T&gt;TreeBag&lt;T&gt; 都提供了在O(1) 中有效地制作树的“快照”或持久副本的能力,允许在修改底层树的同时对快照进行迭代。请注意,树上的每个快照都会对树的更新造成性能损失,但这些影响会在释放快照后消失。

    哈希集合

    • HashSet&lt;T&gt;:使用简单哈希表进行存储的集合。按项目值访问需要 O(1)。作为一个集合,它不允许重复。提供一个函数BucketCostDistribution(),可以帮助你判断item的hashcode函数的效率。
    • HashBag&lt;T&gt;:类似于HashSet&lt;T&gt;,但有包语义,即允许重复,但重复只通过计数存储。

    优先队列

    • IntervalHeap&lt;T&gt;:提供优先级队列。求最大值和最小值是O(1)个操作,删除最大值、最小值、添加和更新是O(log n)个操作.通过显式存储(而不是通过计数)允许重复。

    字典

    • HashDictionary&lt;H,K&gt;:类似于SCG.Dictionary&lt;H,K&gt;,在O(1) 中提供条目访问、插入和删除。还提供了BucketCostDistribution() 函数,如上面的HashSet&lt;T&gt;。不保证任何特定的枚举顺序。
    • TreeDictionary&lt;H,K&gt;:类似于SCG.SortedDictionary&lt;H,K&gt;,使用红黑树提供一个持久排序的字典。条目访问、插入和删除需要 O(log n)。保证字典的枚举遵循键比较器指定的顺序。

    受保护的集合

    同样,C5 还提供“受保护”集合,它有效地充当只读包装器,防止集合被修改。集合中的项目仍然可以修改,但不能添加、删除或插入集合中的项目。

    一个很长的答案,但对 C5 库的各种集合供您使用的详尽。我发现 C5 库很棒,并且经常在我自己的代码中使用它,将常见的 C# 标头替换为:

    using C5;
    using SCG = System.Collections.Generic;
    

    【讨论】:

      【解决方案3】:

      你应该拿起一本关于基本数据结构的书。无论语言如何,都是相同的理论。

      简短说明:

      • Array:(例如int[] myArray)- 可以在集合永不更改时使用的静态数组(您不能添加或删除其中的项目,但您可以更改单个项目的值)
      • ArrayList:通用数组/列表,允许相对快速的枚举以及直接访问。当您添加项目时,此列表会自动增长,但由于它只存储 Object,因此由于性能和类型安全问题,您应该很少使用它。
      • List&lt;T&gt;:上述 ArrayList 的通用版本。它在性能和灵活性之间提供了一个很好的平衡,几乎总是应该在你有一个动态的平面项目列表时使用。 (.NET 2.0 中的新功能)
      • Hashtable:就像一个平面列表一样工作,但不是用整数索引它,它可以使用任何对象索引。值得注意的是,哈希表中没有“顺序”。
      • Dictionary&lt;T&gt;:哈希表的通用版本。在 .NET 2.0 及更高版本中使用它而不是 Hashtable,原因与上面的 ArrayList 与 List 相同。
      • Stack&lt;T&gt;:提供先进后出的列表类型。您最后添加的物品将是您挑选物品时首先收到的物品。
      • Queue&lt;T&gt;:提供先进先出列表。把它想象成一个管子,你可以在其中插入物品并在另一端取出它们。通常用于在例如之间传递消息。线程。

      一般来说,您应该对在 .NET 2.0 及更高版本中所做的几乎所有事情都使用泛型集合。您将获得完整的类型安全性(与例如 ArrayList 和 HashTable 相比),并且与非泛型一次相比,它们对于值类型(整数、结构、浮点数等)要快得多。

      如果您有一个永远不会改变的项目列表,或者您不需要/不想要List&lt;T&gt; 的灵活性,您当然可以使用数组,因为它的开销最少。

      当您从公共方法或属性返回集合时,建议将其转换为不太灵活的接口。因此,如果您有要返回的 List,则可以将其转换为 IEnumerable&lt;int&gt;,这意味着您的消费者无法向其中添加项目(当然,除非它将其转换回,但它仍然是对用户的指示)。转换它还可以让您在以后灵活地更改底层数据结构,同时保持 API 稳定性。您还可以选择ICollection&lt;int&gt;IList&lt;int&gt; 来公开更多功能,但隐藏实际数据结构。

      【讨论】:

      • 这是一个不错的列表 =D 顺便说一句,您可以添加 SortedListSortedDictionary,因为它们通常是真正令人困惑的(即使在 JonSkeet 的回答之后)
      【解决方案4】:

      哈希图

      • 字典
      • 哈希表(非泛型)

      这是一种允许您保留键值对的数据结构。给定一个具有某种排序方式的键,您可以插入一个值。一个简单的示例可以是学生列表,其中键是学生 ID,值是学生姓名。

      随机访问列表

      • 列表
      • ArrayList(非泛型)

      随机访问列表用于存储要随机访问的一长串对象(即您想在 O(1) 时间内访问第 n 个元素)。如果您想在列表中间插入/删除元素,那就不好了,因为这将需要对整个列表进行打乱,这可能需要一些时间。

      链接列表和类似列表

      • 链表
      • 队列
      • 堆栈

      如果您不想访问中间的元素,则链接列表非常有用,因为这将花费 O(N) 时间。如果您想在中间插入/删除元素,那就太好了,因为它只涉及更改几个指针。

      队列和堆栈有些特殊,因为它们针对 FIFO 和 FILO 行为(分别为先进先出和先进先出)进行了优化。

      【讨论】:

      • hashmap 不也是一种随机访问列表吗?
      【解决方案5】:

      如果您从MSDN doco for System.Collections 开始,您可以深入了解各个集合类型,以获取有关这些“列表”以及如何使用它们的更多详细信息。例如,Hashtable 的文档说:“表示基于键的哈希码组织的键/值对的集合。”

      Understanding Generics 中也有关于 System.Collections.Generic 的精彩讨论。

      【讨论】:

        【解决方案6】:

        List 是可排序的,但不建议公开。

        Collection 是一个基本的、没有多余装饰的集合。

        Dictionary 是键值对的集合(很像旧的哈希表,但现在是通用的)。

        KeyedCollection 是一个字典,可以从值中确定键(这是一个抽象,所以你必须继承它并支持GetKey函数)

        ReadOnlyCollection 是一个特殊的集合,内容不能修改。

        ArrayList 和 HashTable 从 .NET 2.0 开始基本上已经过时了。

        【讨论】:

        • 您是否有链接表明已过时?
        【解决方案7】:

        除了到目前为止的出色答案之外,还有更多收藏可通过C5 Generic Collection Library 获得。在根据您的要求决定使用什么时,文档(也在他们的网站上)可能会有所帮助。

        【讨论】:

          【解决方案8】:

          MSDN 有一篇名为 Selecting a Collection Class 的文章,我发现在尝试找出在给定情况下使用哪种集合时非常有用。

          【讨论】:

            【解决方案9】:

            这些是各种类型的general data structures 示例。这些数据结构在软件工程中无处不在。

            【讨论】:

              【解决方案10】:

              如果您在代码窗口中输入System.collections.Generic.,Intellisense 会向您显示每个的简短描述。不要忘记尾随句点。哦,还有System.Collections.ObjectModel.。从那里您应该能够从 MSDN 获得有关任何看起来很有希望的信息的更多信息。

              【讨论】:

                猜你喜欢
                • 2010-11-11
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2011-09-15
                • 2013-12-26
                • 2011-04-06
                • 2010-09-30
                • 1970-01-01
                相关资源
                最近更新 更多