简介

C# 集合框架是处理数据集合的核心组件,位于 System.CollectionsSystem.Collections.Generic 命名空间。它提供了多种数据结构来高效存储和操作数据。

集合框架概览

System.Collections               (非泛型老版)
└─ System.Collections.Generic    (泛型现代版)├─ IList<T>List<T>, LinkedList<T>, ObservableCollection<T>, …├─ ICollection<T>HashSet<T>, SortedSet<T>, …├─ IDictionary<TKey,TValue>Dictionary<TKey,TValue>, SortedDictionary<,>, …└─ IEnumerable<T>
System.Collections.Concurrent    (并发安全集合)
System.Collections.Immutable     (不可变集合)
System.Collections.ObjectModel   (通知模型集合)
  • 非泛型:ArrayList、Hashtable(弃用,不推荐,新代码使用泛型集合)

  • 泛型:类型安全、无装箱,性能更优

核心接口

接口功能
IEnumerable<T>可枚举,支持 foreach
ICollection<T> : IEnumerable<T>增删改查,CountAddRemoveContains
IList<T> : ICollection<T>支持按索引访问,InsertIndexOf
IDictionary<TKey,TValue>键/值对,this[key]TryGetValue
IReadOnlyCollection<T>只读视图
IReadOnlyList<T>只读索引
IReadOnlyDictionary<,>只读字典

主要实现与特性

顺序访问集合
类型特点复杂度(N=Count)
Array固定大小,按索引快速访问读/写 O(1)
List可变大小的数组;增长时可能触发内部扩容读 O(1),插尾 O(1) 摊销;插中间 O(N)
LinkedList双向链表,插入/删除任意节点 O(1)(已知节点);按索引 O(N)访问 O(N),插/删节点 O(1)
ObservableCollection在 UI/MVVM 中使用,修改时触发事件List<T>
键/值对集合
类型特点复杂度
Dictionary<TKey,TValue>哈希表,平均 O(1) 查找/添加/删除查找/添加/删除 O(1)
SortedDictionary<TKey,TValue>基于红黑树,键有序,O(log N) 操作查找/添加/删除 O(log N)
SortedList<TKey,TValue>底层数组,按索引访问快,插入/删除 O(N)访问 O(log N) 二分查找;插/删 O(N)
集合语义的集合
类型特点复杂度
HashSet无序、不重复元素,基于哈希查找/添加/删除 O(1)
SortedSet有序、不重复,基于红黑树查找/添加/删除 O(log N)
Queue先进先出,基于循环数组入队/出队 O(1)
Stack后进先出,基于数组压栈/弹栈 O(1)
BlockingCollection有界/无界并发队列,支持阻塞和取消入/出队 O(1)

并发集合(System.Collections.Concurrent)

类型特点场景
ConcurrentDictionary<,>线程安全的字典,分段锁或自旋锁高并发读写字典
ConcurrentQueue多生产者/多消费者队列并发任务调度
ConcurrentStack并发栈并发回退/撤销操作
ConcurrentBag无序的线程本地存储集合并发任务结果收集
BlockingCollection封装多个并发集合,支持生产者/消费者模式流水线计算

不可变集合(System.Collections.Immutable)

  • ImmutableList<T>, ImmutableDictionary<,>, ImmutableHashSet<T>

  • 特点:每次修改返回新版本,原版本不变;线程安全,适合多读少写场景

var list1 = ImmutableList<int>.Empty;
var list2 = list1.Add(1);

性能选型

  • 频繁随机访问 → List<T> 或 数组

  • 频繁插中间 → LinkedList<T>(谨慎评估 GC/内存)

  • 键/值查找 → Dictionary<,>;需要排序 → SortedDictionary<,>

  • 唯一性 → HashSet<T>;需要有序 → SortedSet<T>

  • 生产者—消费者 → BlockingCollection<T>(可指定底层并发队列)

  • UI 数据绑定 → ObservableCollection<T>

  • 高并发场景 → System.Collections.Concurrent 中的集合

  • 按需 严格不可变 → Immutable*

常见陷阱

  • List<T>.Capacity vs Count:Capacity 控制内部数组长度,Add 超出时会重新 Array.Copy;可通过构造函数预设 Capacity 避免多次扩容。

  • Dictionary 键的 GetHashCode:自定义类型做键时要重写 GetHashCode/Equals,避免哈希冲突。

  • LinkedList<T> 内存碎片:每个节点都是单独对象,GC 压力大时慎用。

  • 并发集合的内存占用:ConcurrentDictionary 分段锁结构会消耗更多内存。

  • 不可变集合:写操作开销高,适合读多写少。

常用集合详解

List<T> - 动态数组
  • 特点:自动扩容、索引访问、支持快速随机访问

  • 最佳场景:需要索引访问的集合,元素数量变化频繁

  • 性能:

    • 添加:平均 O(1),最坏 O(n)(扩容时)

    • 插入/删除:O(n)

    • 访问:O(1)

// 创建与初始化
var numbers = new List<int> { 1, 2, 3 };// 添加元素
numbers.Add(4);
numbers.AddRange(new[] { 5, 6 });// 插入元素
numbers.Insert(0, 0); // 开头插入// 删除元素
numbers.Remove(3);    // 按值删除
numbers.RemoveAt(0);  // 按索引删除// 容量优化(减少内存占用)
numbers.TrimExcess();// 预分配容量(提升性能)
var largeList = new List<int>(capacity: 1000);
Dictionary<K,V> - 哈希字典
  • 特点:键值对存储、快速查找、键唯一

  • 最佳场景:按键快速查找/更新

  • 性能:

    • 查找/添加/删除:平均 O(1),最坏 O(n)(哈希冲突时)
var users = new Dictionary<int, string>
{[1] = "Alice",[2] = "Bob"
};// 安全访问
if (users.TryGetValue(2, out string name))
{Console.WriteLine(name); // 输出 "Bob"
}// 添加或更新
users[3] = "Charlie"; // 添加
users[2] = "Robert";  // 更新// 遍历
foreach (var kvp in users)
{Console.WriteLine($"ID: {kvp.Key}, Name: {kvp.Value}");
}// 自定义键类型(需实现GetHashCode和Equals)
public record UserId(int Id);
var userDict = new Dictionary<UserId, string>();
HashSet<T> - 唯一值集合
  • 特点:元素唯一、快速存在性检查、集合运算

  • 最佳场景:去重操作、集合运算(并集/交集等)

  • 性能:添加/查找/删除 O(1)

var set1 = new HashSet<int> { 1, 2, 3, 4 };
var set2 = new HashSet<int> { 3, 4, 5, 6 };// 集合运算
set1.UnionWith(set2);      // 并集: {1,2,3,4,5,6}
set1.IntersectWith(set2);   // 交集: {3,4}
set1.ExceptWith(set2);      // 差集: {1,2}// 存在性检查
bool contains = set1.Contains(3); // true
SortedSet<T> - 有序唯一集合
  • 特点:元素按升序排列(需实现 IComparable<T>),插入 / 删除 / 查找 O (log n)。

  • 核心方法:同 HashSet<T>,支持 Min、Max 属性。

SortedSet<int> sortedSet = new SortedSet<int> { 3, 1, 2 };
// sortedSet 元素顺序:1, 2, 3int min = sortedSet.Min;  // 最小元素:1
int max = sortedSet.Max;  // 最大元素:3
Queue<T> - 先进先出队列
  • 特点:FIFO(先进先出)处理

  • 最佳场景:任务调度、消息处理

var queue = new Queue<string>();
queue.Enqueue("First");
queue.Enqueue("Second");
queue.Enqueue("Third");while (queue.Count > 0)
{string item = queue.Dequeue();Console.WriteLine(item); // 输出 First → Second → Third
}
Stack<T> - 后进先出栈
  • 特点:LIFO(后进先出)处理

  • 最佳场景:撤销操作、递归算法

var stack = new Stack<int>();
stack.Push(1);
stack.Push(2);
stack.Push(3);while (stack.Count > 0)
{int top = stack.Pop();Console.WriteLine(top); // 输出 3 → 2 → 1
}
LinkedList<T> - 双向链表
  • 特点:高效插入/删除、顺序访问

  • 最佳场景:频繁在中间插入/删除元素

var list = new LinkedList<string>();
var node1 = list.AddFirst("First");
var node3 = list.AddLast("Third");
var node2 = list.AddAfter(node1, "Second");list.Remove(node2);  // 高效删除中间节点// 顺序遍历
var current = list.First;
while (current != null)
{Console.WriteLine(current.Value);current = current.Next;
}
SortedDictionary<K,V>SortedList<K,V>
  • 特点:按键排序的字典

  • 区别:

    • SortedDictionary:基于红黑树,插入删除更快 (O(log n))

    • SortedList:基于数组,内存更紧凑,随机访问更快

并发集合(System.Collections.Concurrent)

ConcurrentDictionary<K,V>
var concurrentDict = new ConcurrentDictionary<int, string>();
concurrentDict.TryAdd(1, "One");
concurrentDict.AddOrUpdate(1, k => "New", (k, v) => "Updated");
ConcurrentQueue<T>
var queue = new ConcurrentQueue<int>();
queue.Enqueue(1);
if (queue.TryDequeue(out int result)) { ... }
ConcurrentBag<T>

无序集合,适用于生产者-消费者场景

var bag = new ConcurrentBag<int>();
bag.Add(42);
if (bag.TryTake(out int item)) { ... }
BlockingCollection - 生产者消费者模型
BlockingCollection<int> buffer = new BlockingCollection<int>(boundedCapacity: 5);// 生产者
Task.Run(() => {for (int i = 0; i < 10; i++) {buffer.Add(i);Thread.Sleep(100);}buffer.CompleteAdding();
});// 消费者
foreach (int item in buffer.GetConsumingEnumerable()) {Console.WriteLine(item);
}

不可变集合(System.Collections.Immutable)

// 创建不可变集合
var immutableList = ImmutableList.Create(1, 2, 3);// 所有"修改"操作返回新集合
var newList = immutableList.Add(4).Remove(2);// 原集合保持不变
Console.WriteLine(immutableList.Count); // 输出 3
Console.WriteLine(newList.Count);       // 输出 3 (添加1个移除1个)
内存安全集合

性能特点:

  • 结构共享:修改操作复用大部分现有内存

  • 线程绝对安全

  • 适合配置对象、历史记录等场景

var builder = ImmutableArray.CreateBuilder<int>();
builder.Add(1);
builder.Add(2);
ImmutableArray<int> immutable = builder.ToImmutable();// 修改操作返回新实例
ImmutableArray<int> newArray = immutable.Add(3);

性能优化技巧

预分配容量:对已知大小的集合初始化时指定容量
var list = new List<int>(1000); // 避免多次扩容
避免装箱拆箱:优先使用泛型集合而非非泛型集合
// 推荐
List<int> intList = new();// 避免
ArrayList oldList = new(); // 导致装箱
批量操作:使用 AddRange() 替代循环中的单个 Add()
// 高效方式
list.AddRange(items);// 低效方式
foreach (var item in items) list.Add(item);
选择合适相等比较器:自定义字典键时实现 IEquatable 和重写 GetHashCode()
public class CustomKey : IEquatable<CustomKey>
{public int Id { get; set; }public bool Equals(CustomKey other) => Id == other?.Id;public override int GetHashCode() => Id.GetHashCode();
}
枚举优化:避免在热路径中创建枚举器
// 低效
for (int i = 0; i < list.Count; i++) { ... }// 高效
int count = list.Count;
for (int i = 0; i < count; i++) { ... }
接口返回只读视图
public IReadOnlyList<string> GetItems()
{return _internalList.AsReadOnly();
}
使用集合初始化器:简洁的初始化语法
var dict = new Dictionary<int, string>
{[1] = "One",[2] = "Two"
};
LINQ结合使用:利用LINQ进行复杂查询
var recentOrders = orders.Where(o => o.Date > DateTime.Now.AddDays(-7)).OrderByDescending(o => o.Total).ToList();
避免修改遍历中的集合:使用 ToList() 创建副本
foreach (var item in collection.ToList())
{if (condition) collection.Remove(item);
}

实践场景

使用 Try 方法

使用 TryGetValue、TryAdd 提高效率

if (dict.TryGetValue(key, out var value))
{// 使用 value
}
相等性实现
public class Person : IEquatable<Person>
{public int Id { get; set; }public bool Equals(Person? other) => other?.Id == Id;public override int GetHashCode() => Id.GetHashCode();
}// 自定义比较器
class CaseInsensitiveComparer : IEqualityComparer<string>
{public bool Equals(string? x, string? y) => string.Equals(x, y, StringComparison.OrdinalIgnoreCase);public int GetHashCode(string obj) => obj.ToUpperInvariant().GetHashCode();
}
枚举安全
// 错误:在枚举中修改集合
foreach (var item in list) {if (item.ShouldRemove) list.Remove(item); // 抛出InvalidOperationException
}// 正确:使用临时集合
List<Item> toRemove = list.Where(item => item.ShouldRemove).ToList();
foreach (var item in toRemove) {list.Remove(item);
}
值类型集合优化
// 避免装箱
List<Point> points = new List<Point>(); // 结构体集合
points.Add(new Point(1, 2));// 优先考虑Span<T>处理内存连续数据
Span<int> span = CollectionsMarshal.AsSpan(numbers);
LRU缓存实现
public class LRUCache<TKey, TValue>
{private readonly Dictionary<TKey, LinkedListNode<CacheItem>> _dict;private readonly LinkedList<CacheItem> _list;private readonly int _capacity;public LRUCache(int capacity){_capacity = capacity;_dict = new Dictionary<TKey, LinkedListNode<CacheItem>>(capacity);_list = new LinkedList<CacheItem>();}public TValue Get(TKey key){if (_dict.TryGetValue(key, out var node)){_list.Remove(node);_list.AddFirst(node);return node.Value.Value;}return default;}public void Add(TKey key, TValue value){if (_dict.Count >= _capacity){var last = _list.Last;_dict.Remove(last.Value.Key);_list.RemoveLast();}var newNode = new LinkedListNode<CacheItem>(new CacheItem { Key = key, Value = value });_list.AddFirst(newNode);_dict.Add(key, newNode);}private class CacheItem{public TKey Key { get; init; }public TValue Value { get; init; }}
}
数据批处理
const int BatchSize = 100;
List<Data> batch = new List<Data>(BatchSize);foreach (var item in massiveCollection)
{batch.Add(item);if (batch.Count == BatchSize){ProcessBatch(batch);batch.Clear();}
}ProcessBatch(batch); // 处理剩余项

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/89129.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/89129.shtml
英文地址,请注明出处:http://en.pswp.cn/web/89129.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网络劫持对用户隐私安全的影响:一场无形的数据窃取危机

在互联网时代&#xff0c;网络劫持如同一把“隐形镰刀”&#xff0c;悄然威胁着用户的隐私安全。当我们在浏览网页、使用社交媒体或进行在线交易时&#xff0c;看似正常的网络连接背后&#xff0c;可能正暗藏着数据被窃取的风险。网络劫持通过多种技术手段干预用户与服务器的正…

使用 Helm 下载 Milvus 安装包(Chart)指南

目录 &#x1f4e6; 使用 Helm 下载 Milvus 安装包&#xff08;Chart&#xff09;指南 &#x1f6e0; 环境准备 &#x1f680; 第一步&#xff1a;添加 Milvus Helm 仓库 &#x1f50d; 第二步&#xff1a;查看可用版本 &#x1f4e5; 第三步&#xff1a;下载指定版本的 C…

EXTI 外部中断

目录 STM32中断 NVIC 中断控制器 NVIC优先级分组 EXTI 外部中断 AFIO 复用IO口 外部中断/事件控制器&#xff08;EXTI&#xff09;框图 STM32中断 在STM32微控制器中&#xff0c;共有68个可屏蔽中断通道&#xff0c;涵盖了多个外设&#xff0c;如外部中断&#xff08;EXT…

WebApplicationType.REACTIVE 的webSocket

通用请求体类 Data ApiModel("websocket请求消息") public class WebSocketRequest<T> implements Serializable {private static final long serialVersionUID 1L;/*** 参考&#xff1a;com.mcmcnet.gacne.basic.service.common.pojo.enumeration.screen.AiB…

降本增效!自动化UI测试平台TestComplete并行测试亮点

在跨平台自动化测试中&#xff0c;企业常面临设备投入高、串行测试耗时长、测试覆盖率难以兼顾的困境。自动化UI测试平台TestComplete的并行测试引擎提供了有效的解决方案&#xff1a;通过云端海量设备池与CI/CD深度集成&#xff0c;实现多平台、多浏览器并行测试&#xff0c;显…

云、实时、时序数据库混合应用:医疗数据管理的革新与展望(上)

云、实时、时序数据库混合应用:医疗数据管理的革新与展望 1、引言 1.1 研究背景与意义 在信息技术飞速发展的当下,医疗行业正经历着深刻的数字化转型。这一转型不仅是技术层面的革新,更是关乎医疗体系未来发展方向的深刻变革。从医疗服务的提供方式,到医疗管理的模式,再…

代码随想录算法训练营十六天|二叉树part06

LeetCode 530 二叉搜索树的最小绝对差 题目链接&#xff1a;530. 二叉搜索树的最小绝对差 - 力扣&#xff08;LeetCode&#xff09; 给你一个二叉搜索树的根节点 root &#xff0c;返回 树中任意两不同节点值之间的最小差值 。 差值是一个正数&#xff0c;其数值等于两值之差…

自增主键为什么不是连续的?

前言 如果一个线程回滚&#xff0c;例如唯一键冲突的情况回滚时&#xff0c;回滚了sql语句&#xff0c;但是并没有把自增的值也-1。那么就会导致下一条插入的数据自增id出现了跳跃。 自增主键为什么不是连续的&#xff1f;前言执行时机为什么自增主键不是连续的为什么不回滚自…

OpenCV图像基本操作:读取、显示与保存

在图像处理项目中&#xff0c;图像的 读取&#xff08;imread&#xff09;、显示&#xff08;imshow&#xff09; 和 保存&#xff08;imwrite&#xff09; 是最基础也是最常用的三个操作。本文将详细介绍这三个函数的功能、用法和注意事项&#xff0c;并提供一个完整示例供读者…

.NET控制台应用程序中防止程序立即退出

在VB.NET控制台应用程序中防止程序立即退出&#xff0c;主要有以下几种常用方法&#xff0c;根据需求选择适合的方案&#xff1a; 方法1&#xff1a;等待用户输入&#xff08;推荐&#xff09; Module Module1Sub Main()Console.WriteLine("程序开始运行...") 这里是…

Vue3 + Three.js 极速入门:打造你的第一个3D可视化项目

文章目录前言一、环境准备1.1 创建Vue3项目1.2 安装Three.js二、Three.js核心概念速览三、实战&#xff1a;创建旋转立方体3.1 组件化初始化四、核心代码解析4.1 Vue3响应式整合技巧4.2 性能优化要点五、进阶功能扩展5.1 数据驱动控制5.2 加载3D模型六、常见问题解决七、资源推…

【设计模式】享元模式(轻量级模式) 单纯享元模式和复合享元模式

享元模式&#xff08;Flyweight Pattern&#xff09;详解一、享元模式简介 享元模式&#xff08;Flyweight Pattern&#xff09; 是一种 结构型设计模式&#xff08;对象结构型模式&#xff09;&#xff0c;它通过共享技术实现相同或相似对象的重用&#xff0c;以减少内存占用和…

驱动开发_2.字符设备驱动

目录1. 什么是字符设备2. 设备号2.1 设备号概念2.2 通过设备号dev分别获取主、次设备号的宏函数2.3 主设备号的申请静态申请动态分配2.4 注销设备号3. 字符设备3.1 注册字符设备3.2 注销字符设备3.3 应用程序和驱动程序的关系3.4 file_opertaions结构体3.5 class_create3.6 创建…

直播推流技术底层逻辑详解与私有化实现方案-以rmtp rtc hls为例-优雅草卓伊凡

直播推流技术底层逻辑详解与私有化实现方案-以rmtp rtc hls为例-优雅草卓伊凡由于我们的甲方客户要开始为我们项目产品上加入私有化的直播&#xff0c;这块不得不又捡起来曾经我们做直播推流的事情了&#xff0c;其实私有化直播一直并不是一件容易的事情&#xff0c;现在大部分…

一文读懂现代卷积神经网络—深度卷积神经网络(AlexNet)

目录 深度卷积神经网络&#xff08;AlexNet&#xff09;是什么&#xff1f; 一、AlexNet 的核心创新 1. 深度架构 2. ReLU 激活函数 3. 数据增强 4. Dropout 正则化 5. GPU 并行计算 6. 局部响应归一化&#xff08;LRN&#xff09; 二、AlexNet 的网络结构 三、AlexN…

JVM 垃圾收集算法全面解析

1. 引言1.1 为什么需要垃圾收集&#xff1f;在Java应用中&#xff0c;垃圾收集&#xff08;Garbage Collection&#xff0c;GC&#xff09;是一个至关重要的机制&#xff0c;它使得开发者不需要手动管理内存。与传统的语言&#xff08;如C或C&#xff09;不同&#xff0c;Java通…

Vmware中安装的CentOS7如何扩展硬盘大小

起初创建虚拟机时&#xff0c;大小设置不合理&#xff0c;导致我在尝试开源项目时空间不足重新扩展硬盘&#xff0c;不仅需要在虚拟机设置中配置&#xff0c;还需要在系统内重新进行分区一、虚拟机设置打开虚拟机设置→硬盘→扩展&#xff0c;将大小设置为自己期望的大小&#…

Python+MongoDB高效开发组合

如大家所知&#xff0c;Python与MongoDB的结合是一种高效的开发组合&#xff0c;主要用于通过Python进行数据存储、查询及管理&#xff0c;利用MongoDB的文档型数据库特性实现灵活的数据处理。下面让 Python 连接上 MongoDB&#xff1a;安装 PyMongo&#xff1a;pip3 install p…

【论文阅读】Masked Autoencoders Are Effective Tokenizers for Diffusion Models

introduce什么样的 latent 空间更适合用于扩散模型&#xff1f;作者发现&#xff1a;相比传统的 VAE&#xff0c;结构良好、判别性强的 latent 空间才是 diffusion 成功的关键。研究动机&#xff1a;什么才是“好的 latent 表征”&#xff1f;背景&#xff1a;Diffusion Models…

每日一SQL 【游戏玩法分析 IV】

文章目录问题案例执行顺序使用分组解决问题 案例 执行顺序 SQL 语句的执行顺序&#xff08;核心步骤&#xff09; 同一层级的select查询内部, 别名在整个 SELECT 计算完成前不生效 使用分组解决 select distinct s.product_id, Product.product_name from Sales sleft join …