【发布时间】:2010-09-16 22:03:31
【问题描述】:
有没有人知道一个很好的资源来简明地解释 C# 中可用的不同类型的列表以及何时适合使用它们?
例如,列表、哈希表、字典等
我不太确定什么时候应该使用什么。
【问题讨论】:
标签: .net collections
有没有人知道一个很好的资源来简明地解释 C# 中可用的不同类型的列表以及何时适合使用它们?
例如,列表、哈希表、字典等
我不太确定什么时候应该使用什么。
【问题讨论】:
标签: .net collections
尽管它们都是集合,但它们并不都是列表。这是一个简短的摘要。
非泛型集合(API 以object 表示。值类型被装箱。
这些大多在System.Collections 命名空间中:
通用集合。 (强类型 API,不会将值类型装箱(假设合适的 T)。
这些大多在System.Collections.Generic namespace:
可能最重要的集合接口是IEnumerable(和IEnumerable<T>)。这表示一个项目序列,就像 Stream 表示一个字节序列一样。没有随机访问,只有前向阅读。 LINQ to Objects 就是基于此,几乎所有的集合类型都实现了它。
【讨论】:
为了解释 tobsen 之前的回答,C5 通用集合库有大量的集合。我将在这里描述其中的一些:
队列/堆栈
CircularQueue<T>:此类提供严格的队列和堆栈功能。同样,使用索引器可以有效O(1) 访问堆栈/队列中的任何项目:cq[0](其中 0 是最旧的项目,接下来要出列,最后要弹出)。列表
注意:ArrayList 和 LinkedList 也可以用作队列/堆栈
ArrayList<T>:与 System.Collections.Generic (SCG)、List<T> 中的对应项类似,它由数组支持,保证 O(1) 索引,但最坏情况 O (n) 插入。O(n) 查找项目。LinkedList<T>:与对应的 SCG.LinkedList<T> 类似。使用双向链表,保证 O(1) 插入,但最坏情况 O(n) 索引(在实践中,是成比例的距离列表的头部或尾部)。还 O(n) 来查找项目。排序使用稳定的合并排序。HashedArrayList<T>:类似于上面的ArrayList<T>,但不允许重复。您获得的回报是查找项目及其索引的时间减少到 O(1)。HashedLinkedList<T>:类似于上面的LinkedList<T>,但不允许重复。和以前一样,找到一个项目的时间减少到 O(1),但找到它的索引的时间仍然是 O(n)。 WrappedArray<T>:与ArrayList<T> 非常相似,它充当实现C5.IList<T> 的数组的包装器,但如果尝试修改集合则抛出异常(IsFixedSize 为真,Add,@但是,987654339@、Insert 不起作用;Sort、Shuffle 和 Reverse 可以,因为它们是就地操作)。列表还提供“查看”功能,它表示底层列表的一部分,允许执行本地操作。使用 C5 书中提供的模式,可以使用对数组和链表都有效的视图来执行操作。任何列表操作也可以在视图上执行,将它们的效果限制在底层列表的子集中。
排序集合
SortedArray<T>:类似于ArrayList<T>,除了它保持其项目排序并且不允许重复。请注意,此集合上的随机插入和删除速度很慢。如果项目数量很少或很少修改但经常通过项目索引或值访问,则此集合是最佳选择。TreeSet<T>:使用红黑树结构来保持项目排序。作为一个集合,它不允许重复。按索引或项值访问以及插入/删除需要 O(log n)。TreeBag<T>:使用红黑树,保持项目排序。作为一个包,它确实允许重复,但不会在树中存储重复,而是通过计数来保持重复。TreeSet<T> 和TreeBag<T> 都提供了在O(1) 中有效地制作树的“快照”或持久副本的能力,允许在修改底层树的同时对快照进行迭代。请注意,树上的每个快照都会对树的更新造成性能损失,但这些影响会在释放快照后消失。
哈希集合
HashSet<T>:使用简单哈希表进行存储的集合。按项目值访问需要 O(1)。作为一个集合,它不允许重复。提供一个函数BucketCostDistribution(),可以帮助你判断item的hashcode函数的效率。HashBag<T>:类似于HashSet<T>,但有包语义,即允许重复,但重复只通过计数存储。优先队列
IntervalHeap<T>:提供优先级队列。求最大值和最小值是O(1)个操作,删除最大值、最小值、添加和更新是O(log n)个操作.通过显式存储(而不是通过计数)允许重复。字典
HashDictionary<H,K>:类似于SCG.Dictionary<H,K>,在O(1) 中提供条目访问、插入和删除。还提供了BucketCostDistribution() 函数,如上面的HashSet<T>。不保证任何特定的枚举顺序。TreeDictionary<H,K>:类似于SCG.SortedDictionary<H,K>,使用红黑树提供一个持久排序的字典。条目访问、插入和删除需要 O(log n)。保证字典的枚举遵循键比较器指定的顺序。受保护的集合
同样,C5 还提供“受保护”集合,它有效地充当只读包装器,防止集合被修改。集合中的项目仍然可以修改,但不能添加、删除或插入集合中的项目。
一个很长的答案,但对 C5 库的各种集合供您使用的详尽。我发现 C5 库很棒,并且经常在我自己的代码中使用它,将常见的 C# 标头替换为:
using C5;
using SCG = System.Collections.Generic;
【讨论】:
你应该拿起一本关于基本数据结构的书。无论语言如何,都是相同的理论。
简短说明:
Array:(例如int[] myArray)- 可以在集合永不更改时使用的静态数组(您不能添加或删除其中的项目,但您可以更改单个项目的值)ArrayList:通用数组/列表,允许相对快速的枚举以及直接访问。当您添加项目时,此列表会自动增长,但由于它只存储 Object,因此由于性能和类型安全问题,您应该很少使用它。List<T>:上述 ArrayList 的通用版本。它在性能和灵活性之间提供了一个很好的平衡,几乎总是应该在你有一个动态的平面项目列表时使用。 (.NET 2.0 中的新功能)Hashtable:就像一个平面列表一样工作,但不是用整数索引它,它可以使用任何对象索引。值得注意的是,哈希表中没有“顺序”。Dictionary<T>:哈希表的通用版本。在 .NET 2.0 及更高版本中使用它而不是 Hashtable,原因与上面的 ArrayList 与 List 相同。Stack<T>:提供先进后出的列表类型。您最后添加的物品将是您挑选物品时首先收到的物品。 Queue<T>:提供先进先出列表。把它想象成一个管子,你可以在其中插入物品并在另一端取出它们。通常用于在例如之间传递消息。线程。一般来说,您应该对在 .NET 2.0 及更高版本中所做的几乎所有事情都使用泛型集合。您将获得完整的类型安全性(与例如 ArrayList 和 HashTable 相比),并且与非泛型一次相比,它们对于值类型(整数、结构、浮点数等)要快得多。
如果您有一个永远不会改变的项目列表,或者您不需要/不想要List<T> 的灵活性,您当然可以使用数组,因为它的开销最少。
当您从公共方法或属性返回集合时,建议将其转换为不太灵活的接口。因此,如果您有要返回的 List,则可以将其转换为 IEnumerable<int>,这意味着您的消费者无法向其中添加项目(当然,除非它将其转换回,但它仍然是对用户的指示)。转换它还可以让您在以后灵活地更改底层数据结构,同时保持 API 稳定性。您还可以选择ICollection<int> 或IList<int> 来公开更多功能,但隐藏实际数据结构。
【讨论】:
SortedList 和 SortedDictionary,因为它们通常是真正令人困惑的(即使在 JonSkeet 的回答之后)
哈希图
这是一种允许您保留键值对的数据结构。给定一个具有某种排序方式的键,您可以插入一个值。一个简单的示例可以是学生列表,其中键是学生 ID,值是学生姓名。
随机访问列表
随机访问列表用于存储要随机访问的一长串对象(即您想在 O(1) 时间内访问第 n 个元素)。如果您想在列表中间插入/删除元素,那就不好了,因为这将需要对整个列表进行打乱,这可能需要一些时间。
链接列表和类似列表
如果您不想访问中间的元素,则链接列表非常有用,因为这将花费 O(N) 时间。如果您想在中间插入/删除元素,那就太好了,因为它只涉及更改几个指针。
队列和堆栈有些特殊,因为它们针对 FIFO 和 FILO 行为(分别为先进先出和先进先出)进行了优化。
【讨论】:
如果您从MSDN doco for System.Collections 开始,您可以深入了解各个集合类型,以获取有关这些“列表”以及如何使用它们的更多详细信息。例如,Hashtable 的文档说:“表示基于键的哈希码组织的键/值对的集合。”
Understanding Generics 中也有关于 System.Collections.Generic 的精彩讨论。
【讨论】:
List
Collection
Dictionary
KeyedCollection
ReadOnlyCollection
ArrayList 和 HashTable 从 .NET 2.0 开始基本上已经过时了。
【讨论】:
除了到目前为止的出色答案之外,还有更多收藏可通过C5 Generic Collection Library 获得。在根据您的要求决定使用什么时,文档(也在他们的网站上)可能会有所帮助。
【讨论】:
MSDN 有一篇名为 Selecting a Collection Class 的文章,我发现在尝试找出在给定情况下使用哪种集合时非常有用。
【讨论】:
这些是各种类型的general data structures 示例。这些数据结构在软件工程中无处不在。
【讨论】:
如果您在代码窗口中输入System.collections.Generic.,Intellisense 会向您显示每个的简短描述。不要忘记尾随句点。哦,还有System.Collections.ObjectModel.。从那里您应该能够从 MSDN 获得有关任何看起来很有希望的信息的更多信息。
【讨论】: