C# 集合(Collection)是用于数据存储和检索的核心数据结构,支持动态内存管理、多种数据组织形式及高效操作。以下是其核心特性和分类:
一、集合的核心作用
1、动态扩展
集合可动态调整容量(如 List),相比固定大小的数组更灵活。
2、多样化数据结构
提供栈(Stack)、队列(Queue)、列表(List)、哈希表(Dictionary<TKey,TValue>)等结构,适应不同场景需求
3、高效操作
通过哈希表、平衡树等结构优化查找、插入和删除操作的性能
二、C# 集合的核心分类
C# 集合主要分为 泛型集合 和 非泛型集合,分别位于 System.Collections.Generic 和 System.Collections 命名空间。
此外,还有 线程安全集合(System.Collections.Concurrent)和 特殊用途集合(如 ObservableCollection)。
核心接口
所有集合类型基于以下接口实现:
接口 | 作用 |
---|---|
IEnumerable | 支持集合遍历(如 foreach) |
ICollection | 定义集合大小、同步操作等基础功能 |
IList/IDictionary | 提供索引或键值对访问(如 List、Dictionary) |
三、常用集合类型详解及对比
1. 动态数组
类型 | 特点 | 适用场景 |
---|---|---|
List | 泛型动态数组,支持索引、动态扩容,高效增删(尾部操作O(1),中间操作O(n)) | 需频繁修改的强类型数据集合 |
ArrayList | 非泛型动态数组,存储object,需装箱/拆箱,类型不安全 | 旧代码兼容,非泛型场景 |
示例代码
List<int> numbers = new List<int> { 1, 2, 3 };
numbers.Add(4); // O(1)(若未扩容)
numbers.RemoveAt(0); // O(n)
2. 键值对集合
类型 | 特点 | 适用场景 |
---|---|---|
Dictionary<TKey,TValue> | 泛型哈希表,键唯一,查找/插入/删除接近O(1) | 高频键值查询(如缓存) |
Hashtable | 非泛型哈希表,键值均为object,性能较低 | 旧代码兼容 |
SortedDictionary<TKey,TValue> | 基于红黑树实现,按键排序,插入/删除O(log n) | 需要有序键值对的场景 |
示例代码
Dictionary<string, int> scores = new Dictionary<string, int>();
scores.Add("Alice", 90); // O(1)
int aliceScore = scores["Alice"]; // O(1)
3. 队列与栈
类型 | 特点 | 适用场景 |
---|---|---|
Queue | 先进先出(FIFO),入队/出队均为O(1) | 任务调度、消息缓冲 |
Stack | 后进先出(LIFO),入栈/出栈均为O(1) | 撤销操作、递归模拟 |
示例代码
Queue<string> tasks = new Queue<string>();
tasks.Enqueue("Task1"); // O(1)
string nextTask = tasks.Dequeue(); // O(1)
4. 链表
类型 | 特点 | 适用场景 |
---|---|---|
LinkedList | 双向链表,插入/删除任意位置O(1)(需先找到节点),内存占用较高 | 高频插入删除,无需索引访问 |
示例代码
LinkedList<int> linkedList = new LinkedList<int>();
linkedList.AddLast(10); // O(1)
linkedList.AddFirst(5); // O(1)
5. 其他特殊集合
类型 | 特点 |
---|---|
HashSet | 无序、唯一元素集合,基于哈希表,查找/插入O(1) |
SortedSet | 有序唯一元素集合,基于红黑树,插入/删除O(log n) |
ObservableCollection | 数据变化时触发通知(如WPF绑定) |
四、集合选择的核心原则
1、数据类型安全
- 优先使用泛型集合(如 List 而非 ArrayList),避免装箱拆箱和运行时错误。
2、访问方式
- 按索引访问:List 或数组。
- 按键访问:Dictionary<TKey,TValue>。
3、性能需求
- 高频插入/删除:LinkedList(中间操作)或 List(尾部操作)。
- 快速查找:哈希表(Dictionary)。
4、线程安全
- 多线程场景使用 ConcurrentQueue、ConcurrentDictionary 等并发集合。
5、内存效率
- 数据量固定时优先用数组,动态调整时用集合。
五、关键区别总结
集合类型 | 内部结构 | 时间复杂度(平均) | 适用场景 |
---|---|---|---|
List | 动态数组 | 索引访问O(1),中间增删O(n) | 通用动态数据存储 |
Dictionary<TKey,TValue> | 哈希表 | 查找/插入/删除接近O(1) | 高频键值查询 |
LinkedList | 双向链表 | 插入/删除O(1) | (需先查找节点) |
HashSet | 哈希表 | 查找/插入/删除O(1) | 去重、集合运算(交/并集) |
SortedSet | 红黑树 | 插入/删除O(log n) | 需要有序唯一元素的场景 |
六、最佳实践
- 初始化容量:预估数据量,避免频繁扩容(如 new List(1000))。
- 避免频繁修改:对 List 中间元素的大量增删可改用 LinkedList。
- 线程安全:非并发集合在多线程中需手动加锁,或直接使用 Concurrent 集合。
- 通过合理选择集合类型,可以在代码可读性、性能和内存效率之间达到最佳平衡。