当前位置: 首页 > news >正文

C#基础13-泛型集合

零、文章目录

C#基础13-泛型集合

1、List(动态数组)

(1)核心特性与优势
  • 类型安全
    • 强制元素类型一致(如 List<int> 只存整数),避免 ArrayList 的装箱拆箱开销。
    • 编译时类型检查,减少运行时错误。
  • 动态扩容
    • 初始容量默认为 4,添加元素超限时自动倍增容量(如 4→8→16)。
    • 可通过 Capacity 属性查看当前容量,Count 获取实际元素数。
  • 高效内存管理
    • 连续内存存储,支持快速索引访问(时间复杂度 O(1))。
    • 对比数组:无需手动扩容,对比 ArrayList:避免值类型装箱。
(2)基础操作(增删查改)
  • 初始化与添加元素
// 创建空列表 
List<string> names = new List<string>();  // 添加单个元素 
names.Add("Alice");  // 添加集合 
string[] newNames = { "Bob", "Charlie" };
names.AddRange(newNames);  // 插入元素到指定位置 
names.Insert(1, "David");  // 索引1位置插入 
  • 删除元素
names.Remove("Alice");     // 删除首个匹配项 
names.RemoveAt(0);         // 删除索引0的元素 
names.RemoveRange(1, 2);   // 从索引1开始删2个元素 
names.Clear();             // 清空列表 
  • 查询与判断
bool hasBob = names.Contains("Bob");  // 检查存在性 
int index = names.IndexOf("Charlie"); // 获取首个匹配索引 
string first = names[0];              // 通过索引访问 
(3)进阶操作与高阶方法
  • 批量筛选与转换
    • FindAll + 谓词:返回满足条件的所有元素
List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
List<int> evens = numbers.FindAll(n => n % 2 == 0);  // [2, 4]
- `ConvertAll`:类型转换(如 `int` → `string`)  
List<string> numStrings = numbers.ConvertAll(n => n.ToString());
  • 委托与 Lambda 应用
// 查找首个大于3的元素 
int target = numbers.Find(n => n > 3);  // 4 // 检查所有元素是否满足条件 
bool allPositive = numbers.TrueForAll(n => n > 0);  // true 
  • 排序与反转
numbers.Sort();                      // 默认升序 [1,2,3,4,5]
numbers.Reverse();                   // 反转 [5,4,3,2,1]
numbers.Sort((a, b) => b.CompareTo(a)); // 自定义降序 
(4)性能优化与避坑指南
  • 预设容量:提前设置 Capacity 避免频繁扩容:
List<int> bigList = new List<int>(1000);  // 初始容量1000 
  • 避免遍历中修改集合:使用 for 循环替代 foreach 删除元素,防止 InvalidOperationException
  • 值类型集合优化:对大量结构体(struct)使用 List<ValueType> 减少堆内存分配。
  • 批量操作优先:用 AddRange() 替代多次 Add(),减少扩容次数。
(5)典型应用场景
  • 数据绑定:作为 DataGridView 数据源:
dataGridView.DataSource = new BindingList<Person>(personList);
  • API 数据处理:反序列化 JSON 数组 → List<T>
List<User> users = JsonConvert.DeserializeObject<List<User>>(json);
  • 高效集合运算:使用 LINQ 扩展方法(需 using System.Linq):
var union = list1.Union(list2).ToList();  // 并集 
var difference = list1.Except(list2);     // 差集 

2、Dictionary<TKey, TValue>(键值对字典)

(1)核心特性与优势
  • 哈希表实现
    • 基于哈希表存储键值对,提供接近 O(1) 的查找效率(性能取决于键的哈希算法质量)。
    • 示例:Dictionary<string, int> 比遍历 List 查找快数十倍。
  • 类型安全与强类型约束
    • 键 (TKey) 和值 (TValue) 均为泛型,编译时检查类型错误,避免 Hashtable 的装箱拆箱开销。
  • 动态扩容机制
    • 初始容量默认为 0,首次添加元素时扩容至 4,后续按指数级增长(4→8→16)。
    • 通过 Capacity 属性预设容量减少扩容开销。
(2)基础操作与语法
  • 初始化与增删改查
// 初始化 
var scores = new Dictionary<string, int>(); // 添加元素(键必须唯一)
scores.Add("Alice", 90);  
scores["Bob"] = 85;        // 索引器方式 // 删除元素 
scores.Remove("Alice");// 修改值 
scores["Bob"] = 95; // 安全取值(避免KeyNotFoundException)
if (scores.TryGetValue("Bob", out int score)) 
{Console.WriteLine(score); // 输出 95
}
  • 注意:直接通过 scores["Unknown"] 访问不存在的键会抛出异常。
  • 键值约束
    • 键 (TKey):不可为 null,且对象作为键时禁止修改影响哈希值的属性。
    • 值 (TValue):可为 null(若 TValue 是引用类型)。
(3)遍历字典的四种方式
方法语法示例适用场景
遍历 KeyValuePairforeach (var kvp in dict) { kvp.Key }需同时访问键和值(最常用)
单独遍历键集合foreach (var key in dict.Keys) { }仅需处理键(如批量删除)
单独遍历值集合foreach (var value in dict.Values) { }仅需统计或处理值
通过索引访问键var key = dict.ElementAt(0).Key;需按插入顺序访问(不推荐)
  • 提示:Dictionary 的元素顺序与添加顺序无关,需有序存储请改用 SortedDictionary
(4)高级应用场景
  • 数据缓存:利用 O(1) 查询特性存储频繁访问的数据(如数据库查询结果):
private static Dictionary<int, Product> _productCache = new();
public Product GetProduct(int id)
{if (!_productCache.TryGetValue(id, out var product)){product = FetchFromDatabase(id); _productCache.Add(id, product);}return product;
}
  • 配置项管理:存储应用程序配置(如环境变量、用户设置):
var configs = new Dictionary<string, string> 
{["Theme"] = "Dark",["Timeout"] = "30"
};
  • 分组统计:快速聚合数据(如按类别计数):
var words = new List<string> { "apple", "banana", "apple" };
var countDict = new Dictionary<string, int>();
foreach (var word in words)
{countDict[word] = countDict.TryGetValue(word, out int count) ? count + 1 : 1;
}
(5)性能优化与陷阱规避
  • 预设初始容量:已知元素数量时,构造器指定容量避免多次扩容:var dict = new Dictionary<string, int>(capacity: 1000);
  • 避免修改键对象:若键对象被修改导致哈希值变化,该键将无法被检索到。
  • 线程安全问题:Dictionary 非线程安全,多线程环境需改用 ConcurrentDictionary 或手动加锁。
  • 优先使用 TryGetValue:比先 ContainsKey 再取值减少一次哈希计算。
(6)与相似类型的对比
集合类型特点适用场景
Dictionary哈希表实现,查询极快高频键值查找、缓存
SortedDictionary红黑树实现,按键排序需有序遍历键值对
Hashtable非泛型,需装箱拆箱遗留代码兼容(不推荐新项目)
ConcurrentDictionary线程安全版本多线程共享字典

3、Queue(先进先出队列)

(1)核心特性
  • 先进先出(FIFO)
    • 元素从队尾入队(Enqueue),从队头出队(Dequeue),确保最早加入的元素最先被处理。
    • 示例:
Queue<string> queue = new Queue<string>();
queue.Enqueue("First");  // 队尾添加 
queue.Enqueue("Second");
string firstItem = queue.Dequeue(); // 移除并返回"First"
  • 线程安全性
    • 非线程安全:默认实现不支持多线程并发操作,需手动加锁或使用 ConcurrentQueue<T>
    • 线程安全替代方案:
ConcurrentQueue<int> concurrentQueue = new ConcurrentQueue<int>();
concurrentQueue.Enqueue(100); // 线程安全入队 
  • 允许重复值与 null
    • 可存储重复元素,且接受 null 作为有效值(若 T 为引用类型)。
(2)基础操作与方法
方法/属性作用示例
Enqueue(T item)添加元素到队尾queue.Enqueue("NewItem");
Dequeue()移除并返回队头元素(队列为空时抛异常)string item = queue.Dequeue();
Peek()查看队头元素但不移除string head = queue.Peek();
Count获取队列中元素数量int num = queue.Count;
Contains(T item)检查元素是否存在bool exists = queue.Contains("A");
Clear()清空队列queue.Clear();
ToArray()将队列转为数组(顺序:队头→队尾)string[] arr = queue.ToArray();
(3)使用注意事项
  • 容量与性能优化
    • 默认初始容量为 4,扩容时容量翻倍(2×)。可通过构造函数指定初始容量减少扩容开销:
Queue<int> optimizedQueue = new Queue<int>(100); // 初始容量100 
- 调用 `TrimExcess()` 释放多余内存(当元素数 < 容量的90%时有效)。
  • 避免空队列操作:调用 Dequeue()Peek() 前需检查队列是否为空,否则抛出 InvalidOperationException
if (queue.Count > 0) {var item = queue.Dequeue();
}
(4)典型应用场景
  • 任务调度系统:按提交顺序处理任务(如订单处理、日志消费):
Queue<Action> taskQueue = new Queue<Action>();
taskQueue.Enqueue(() => Console.WriteLine("Task 1"));
taskQueue.Enqueue(() => Console.WriteLine("Task 2"));
while (taskQueue.Count > 0) {taskQueue.Dequeue().Invoke(); // 按序执行 
}
  • 广度优先搜索(BFS):遍历树或图结构时,用队列管理待访问节点:
Queue<TreeNode> nodes = new Queue<TreeNode>();
nodes.Enqueue(rootNode);
while (nodes.Count > 0) {var current = nodes.Dequeue();// 处理当前节点,子节点入队...
}
  • 消息缓冲机制:在多线程环境中,用 ConcurrentQueue<T> 实现生产者-消费者模型:
// 生产者线程 
concurrentQueue.Enqueue(newMessage);
// 消费者线程 
if (concurrentQueue.TryDequeue(out var msg)) {ProcessMessage(msg);
}
(5)与其他集合对比
集合类型顺序允许重复线程安全适用场景
Queue<T>FIFO❌(需手动同步)顺序任务处理、BFS
Stack<T>LIFO撤销操作、递归算法
ConcurrentQueue<T>FIFO高并发生产者-消费者模型
List<T>索引随机访问、动态数组需求

4、Stack(后进先出栈)

(1)核心特性
  • 后进先出(LIFO)结构:元素按插入顺序反向处理,最后添加的元素最先被移除。
(2)基础操作与方法
  • 初始化
Stack<int> stack = new Stack<int>();          // 空栈,默认容量 
Stack<string> stack2 = new Stack<string>(10); // 指定初始容量
  • Push(T item):元素压入栈顶。
stack.Push(1); 
stack.Push(2); // 栈顶元素为 2
  • Pop():移除并返回栈顶元素(栈空时抛 InvalidOperationException)。
int top = stack.Pop(); // 返回 2
  • Peek():查看栈顶元素不移除。
int currentTop = stack.Peek(); // 返回 1
  • TryPop(out T result) & TryPeek(out T result):安全操作,避免异常。
if (stack.TryPop(out int value)) 
{Console.WriteLine($"弹出元素:{value}");
}
(3)进阶用法与实践技巧
  • 遍历:遍历顺序为栈顶到栈底(逆插入顺序)
foreach (var item in stack) 
{Console.WriteLine(item); // 输出顺序:2 → 1 
}
  • 反转顺序:需转换为数组后反转。
var reversed = stack.ToArray().Reverse();
  • 资源清理与容量优化
    • 手动释放资源:结合 Clear() 清空栈元素。
    • 减少内存占用:调用 TrimExcess() 释放未用空间(当元素数小于容量的90%时生效)。
  • 线程安全场景
    • 多线程环境下使用 ConcurrentStack<T>
var concurrentStack = new ConcurrentStack<int>();
concurrentStack.Push(10);
concurrentStack.TryPop(out int result);
(4)性能与底层机制
  • 时间复杂度
    • Push()Pop() 操作在未触发扩容时为 O(1);扩容时(容量翻倍)为 O(n)。
    • Peek() 始终为 O(1)。
  • 内部实现
    • 基于动态数组存储,自动扩容策略为当前容量的 2 倍。
    • 初始容量过小可能导致频繁扩容,建议预估规模初始化。
  • 对比非泛型 Stack
    • 类型安全:避免装箱拆箱(值类型)和强制转换风险。
    • 性能提升:泛型版本减少运行时开销。
(5)典型应用场景
  • 撤销/重做功能:用两个栈分别存储操作记录:
Stack<ICommand> _undoStack = new Stack<ICommand>();
Stack<ICommand> _redoStack = new Stack<ICommand>();// 执行操作
public void Execute(ICommand cmd) 
{cmd.Execute();_undoStack.Push(cmd);_redoStack.Clear(); // 清空重做栈
}// 撤销操作 
public void Undo() 
{if (_undoStack.TryPop(out ICommand cmd)) {cmd.Undo();_redoStack.Push(cmd);}
}
  • 深度优先搜索(DFS):递归算法的迭代实现
Stack<TreeNode> stack = new Stack<TreeNode>();
stack.Push(rootNode);
while (stack.Count > 0) 
{var node = stack.Pop();Process(node);foreach (var child in node.Children.Reverse()) {stack.Push(child); // 逆序压入子节点}
}
(6)注意事项
  • 空栈处理:调用 Pop()Peek() 前检查 Count 属性,或使用 TryPop/TryPeek 方法。
if (stack.Count > 0) 
{var item = stack.Peek();
}
  • 允许 null 值:引用类型栈可插入 null,需注意空值判断:
Stack<string> strStack = new Stack<string>();
strStack.Push(null); // 合法操作

5、HashSet(无序唯一集合)

(1)核心特性与底层机制
  • 唯一性与无序性
    • 元素唯一:自动过滤重复项(依赖 Equals()GetHashCode() 的正确实现)。
    • 无序存储:基于哈希表实现,不保证元素顺序(与 List<T> 的顺序存储对比鲜明)。
  • 高效操作
    • 时间复杂度:
      • Add()/Remove()/Contains():平均 O(1)(哈希冲突时退化至 O(n))。
      • 对比 List<T>Contains() 需遍历(O(n)),大数据量时性能差距显著。
    • 动态扩容:容量翻倍策略,预初始化可优化性能(如 new HashSet<T>(capacity))。
  • 允许 null
    • 引用类型可插入 null,需额外判空处理。
️(2)核心方法
  • 基础操作示例
var emails = new HashSet<string>();
emails.Add("user@example.com");   // 添加成功 → true
emails.Add("user@example.com");   // 添加失败 → false(重复忽略)
bool exists = emails.Contains("user@example.com");  // 检查存在 → true 
emails.Remove("user@example.com");
  • 集合运算(高频应用)
方法作用示例
UnionWith()并集(合并集合)set1.UnionWith(set2);
IntersectWith()交集(共同元素)set1.IntersectWith(set2);
ExceptWith()差集(移除共有元素)set1.ExceptWith(set2);
SymmetricExceptWith()对称差集(独有元素)set1.SymmetricExceptWith(set2);
(3)典型场景
  • 数据去重:替代 List<T> 的遍历去重,效率更高。
int[] numbers = { 1, 2, 2, 3, 4 };
var uniqueSet = new HashSet<int>(numbers); // 结果:{1, 2, 3, 4}
  • 快速检索:如用户邮箱唯一性校验(10万级数据比 List<T> 快百倍):
if (emailSet.Contains(inputEmail)) // O(1) 完成校验
  • 内存数据库缓存:高频访问数据用 HashSet 缓存,减少数据库查询(需定时刷新防回收)。
(4)与 List<T> 的关键对比
维度HashSet<T>List<T>
唯一性✅ 强制唯一❌ 允许重复
顺序性❌ 无序✅ 保留插入顺序
查找性能O(1)(哈希直接定位)🐢 O(n)(需遍历)
内存占用更低(无重复预留空间)更高(可能预留多余容量)
适用场景去重、集合运算、高频检索顺序访问、索引操作、允许重复
️(5)注意事项与进阶技巧
  • 线程安全:非线程安全!多线程环境需用 ConcurrentDictionary<T, byte> 或加锁。
  • 哈希冲突优化
    • 重写 GetHashCode() 确保散列均匀(避免大量冲突导致性能下降)。
  • 内存回收
    • 调用 TrimExcess() 释放未用空间(元素数 < 容量的 90% 时生效)。
  • 与 LINQ 结合
    • 支持 LINQ 操作,但部分方法(如 Distinct())在 HashSet 中冗余:
var evenNumbers = numberSet.Where(n => n % 2 == 0); // 直接过滤
http://www.dtcms.com/a/463524.html

相关文章:

  • 建立一个平台网站需要多少钱重庆装修公司全包价格
  • 厦门网站免费制作万能视频下载神器
  • Linux小课堂: 理解命令行提示符与基本命令使用
  • 备案网站名称与实际网站名称不一致郑州网站建设方案优化
  • 做网站通常到哪找图片学校网页制作视频教程
  • 管理网站模板下载免费一键优化表格
  • 贵阳汽车网站建设四川攀枝花网站建设
  • wordpress 局域网天津网站seo策划
  • 动漫建模代做网站百度一下一个做flash的网站
  • 站长统计app下载免费公司推广网站建设话术
  • 哪种源码做视频网站好用自媒体135软件
  • 旅游网站建设初衷呼叫中心系统厂家排名
  • 做公司网站哪家好 上海网站建设教程pdf百度云
  • CNN卷积计算
  • 石家庄建设局官方网站wordpress图片主题破解
  • 网站添加文字大小小制作小发明简单做法
  • 网站建没有前景网址大全有用吗
  • 模板王网站怎么下载不了模板微信游戏小程序代理
  • 杭州做网站哪个公司好阳江房产网官网查询
  • 漳浦县建设局网站济南个人制作网站
  • 湖北望新建设有限公司网站网站建设服务器费用
  • 厦门学网站建设美食网页界面设计
  • 自己做的网站如何上首页设计与绘制一个网站首页
  • redis的红锁
  • 网站空间的控制面板首页如何添加网站代码
  • 电商网站的成本做网站的视频
  • Python实例方法与Python类的构造方法全解析
  • 网站关键词突然搜不到了标签在数据库wordpress
  • 公司网站 正式上线asp网站有哪些
  • 免费凡科网站wordpress程序覆盖