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

C#基础14-非泛型集合

零、文章目录

C#基础14-非泛型集合

1、ArrayList

(1)核心特性
  • 动态数组
    • 无需预先定义固定长度,容量随元素增减自动调整(默认初始容量为 4,扩容时通常加倍)。
    • 支持任意类型元素(存储为 object 类型),可混合存放字符串、整数等。
  • 底层实现
    • 继承 System.Collections 命名空间,实现 IListICollection 等接口。
    • 非泛型集合,依赖装箱(值类型→object)和拆箱(object→值类型)操作。
(2)基本操作与示例
using System.Collections;ArrayList al = new ArrayList();
// 添加元素 
al.Add("Apple");         // 末尾添加 
al.Insert(0, 123);       // 索引0插入整数 
al.AddRange(new[] { "Banana", 4.5 }); // 添加集合 // 删除元素
al.Remove("Apple");      // 移除首个匹配项 
al.RemoveAt(0);          // 移除索引0元素 
al.Clear();              // 清空// 查找与排序
int index = al.IndexOf("Banana"); // 返回索引
al.Sort();               // 默认排序(需元素可比)
al.Reverse();            // 反转顺序 
(3)优缺点分析
优点缺点
✅ 动态扩容,无需预设大小❌ 类型不安全:编译期无类型检查,运行时易出错
✅ 灵活插入/删除(Insert/Remove❌ 性能损耗:值类型操作需装箱拆箱,效率低
✅ 支持多种数据混合存储❌ 非线程安全:多线程需手动同步
(4)与 List<T> 的对比
特性ArrayListList<T>(泛型)
类型安全❌ 存储 object 类型✅ 编译时类型检查
性能❌ 装箱拆箱开销大✅ 无需装箱拆箱,效率高
内存占用❌ 扩容频繁可能浪费内存✅ 容量管理更高效
推荐场景遗留代码维护新项目首选,尤其值类型操作
(5)注意事项
  • 线程安全:需通过 ArrayList.Synchronized() 创建线程安全版本。
  • 排序限制:混合类型时调用 Sort() 会抛出 InvalidOperationException,需确保元素可比。

2、Hashtable

(1)核心特性
  • 键值对存储
    • key-value 形式存储数据,键和值均为 object 类型,支持任意数据类型(如字符串、整数、自定义对象)。
    • 键唯一性:键不能重复,尝试插入重复键会覆盖原有值。
  • 哈希算法驱动
    • 通过键的哈希码(GetHashCode() 生成)定位数据存储位置,实现 O(1) 平均时间复杂度的快速查找。
    • 自动处理哈希冲突:采用链地址法(冲突键值对存储在同一个桶的链表中)。
  • 动态扩容
    • 初始默认容量为 0(首次添加元素时扩容至合理值),当元素数量超过当前容量与负载因子(默认 0.75)乘积时,自动扩容并重新分配存储。
  • 非泛型与非线程安全
    • 位于 System.Collections 命名空间,存储时需装箱拆箱(值类型→object),性能低于泛型集合。
    • 默认非线程安全,多线程读写需通过 Hashtable.Synchronized() 包装或手动加锁。
(2)基础用法
  • 初始化与增删改查
using System.Collections;Hashtable ht = new Hashtable();
// 添加键值对 
ht.Add("id", 1001);       // 键为字符串,值为整数
ht["name"] = "Alice";     // 索引器方式添加/修改 
ht.Add(3.14, "Pi");       // 键为浮点数,值为字符串// 删除元素 
ht.Remove("id");          // 移除指定键 
ht.Clear();               // 清空所有元素// 查询与判断
if (ht.ContainsKey("name")) Console.WriteLine(ht["name"]); // 输出:Alice 
if (ht.ContainsValue(1001)) Console.WriteLine("Value exists!");
  • 避免类型转换错误的技巧
// 使用 as 操作符安全转换
string name = ht["name"] as string;
if (name != null) { /* 安全操作 */ }// 使用 is 类型检查 
if (ht["id"] is int id) Console.WriteLine($"ID: {id}");
  • 遍历方式
// 遍历所有键
foreach (object key in ht.Keys) Console.WriteLine($"Key: {key}");// 遍历所有值 
foreach (object value in ht.Values) Console.WriteLine($"Value: {value}");// 遍历键值对(推荐)
foreach (DictionaryEntry de in ht) Console.WriteLine($"{de.Key} : {de.Value}");
  • 排序(通过键间接实现)
ArrayList keys = new ArrayList(ht.Keys);
keys.Sort(); // 对键排序 
foreach (string key in keys) Console.WriteLine($"{key}: {ht[key]}");
️(3)与 Dictionary<TKey, TValue> 对比
特性HashtableDictionary<TKey, TValue>
类型安全❌ 需手动类型转换✅ 编译时类型检查
性能❌ 值类型操作需装箱拆箱,效率低✅ 无装箱拆箱,速度快20%-50%
线程安全❌ 需额外同步机制❌ 默认非线程安全(可用并发集合替代)
顺序保证❌ 无序存储✔️ .NET Core 3.0+ 默认按插入顺序遍历
推荐场景遗留代码维护、需混合类型存储新项目首选,高性能场景
️(4)注意事项
  • 键不可为 null:尝试添加 null 键会抛出 ArgumentNullException
  • 哈希码依赖:自定义对象作为键时,需重写 GetHashCode()Equals() 方法,确保哈希一致性。
  • 混合类型排序风险:若键类型不一致(如字符串与整数混合),调用 Sort() 可能抛出 InvalidOperationException

3、Queue

(1)核心特性
  • 先进先出(FIFO)机制
    • 元素按插入顺序处理,队头元素(最早入队)优先被移除。
    • 典型场景:任务调度、消息传递、缓冲区管理(如日志处理)。
  • 动态扩容
    • 初始容量为 0(首次添加时自动扩容),当元素数量超过当前容量时自动扩容(通常加倍)。
    • 支持手动调整容量:TrimToSize() 优化内存。
  • 非泛型与泛型实现
    • System.Collections.Queue:存储 object 类型,需装箱拆箱,类型不安全。
    • System.Collections.Generic.Queue<T>:泛型版本,类型安全且无需装箱拆箱。
  • 基础操作高效性
    • 入队(Enqueue)、出队(Dequeue)、查看队头(Peek)操作时间复杂度为 O(1)。
(2)基础用法
  • 创建与增删操作
using System.Collections.Generic;Queue<string> queue = new Queue<string>();
// 入队 
queue.Enqueue("Task1");
queue.Enqueue("Task2");// 出队 
string task = queue.Dequeue(); // 返回 "Task1"
// 查看队头(不移除)
string nextTask = queue.Peek(); // 返回 "Task2"// 清空队列 
queue.Clear();
  • 遍历与判断
// 遍历所有元素 
foreach (var item in queue) {Console.WriteLine(item);
}// 判断元素存在性 
if (queue.Contains("Task2")) {Console.WriteLine("任务存在");
}
  • 线程安全处理
// 多线程环境下需手动同步 
lock (queue) {queue.Enqueue("ConcurrentTask");
}
(3)优缺点分析
优点缺点
✅ 动态扩容,无需预设大小❌ 非泛型版本需装箱拆箱,性能损耗
✅ FIFO 机制保证处理顺序❌ 默认非线程安全,需额外同步
✅ 基础操作(入队/出队)高效❌ 无法直接访问队列中间元素
(4)与现代替代方案对比
  • ConcurrentQueue<T>(并发队列)
特性Queue<T>ConcurrentQueue<T>
线程安全❌ 需手动加锁✅ 无锁实现,内置线程安全
性能✅ 单线程下更快✅ 高并发下性能更优(避免锁竞争)
API 设计Enqueue/DequeueTryEnqueue/TryDequeue(避免异常)
适用场景单线程或低并发任务高并发场景(如并行计算、消息队列)
  • 性能测试参考(百万次操作)
操作Queue<T> 耗时ConcurrentQueue<T> 耗时
单线程入队15 ms20 ms
多线程入队崩溃(线程竞争)35 ms
  • Channel(.NET Core 3.0+)
    • 定位:异步消息队列,替代生产者-消费者模式中的 ConcurrentQueue
    • 优势:
      • 支持异步写入(WriteAsync)和读取(ReadAsync)。
      • 内置背压控制(限制队列长度)。
(5)使用建议
  • 首选泛型版本:新项目一律使用 Queue<T>,避免类型转换和装箱开销。
  • 并发场景选择
    • 多线程任务调度 → ConcurrentQueue<T>
    • 异步数据流处理 → Channel
  • 避免混合类型:非泛型 Queue 仅用于遗留代码维护或未知类型数据(如动态解析 JSON)。

4、Stack

(1)核心特性
  • 后进先出(LIFO)机制
    • 最后添加的元素最先被移除,适用于撤销操作、表达式求值等场景。
  • 动态扩容
    • 初始容量为 0(首次添加时自动扩容),元素超限时容量加倍。
  • 两种实现方式
    • System.Collections.Stack:非泛型,存储 object 类型,需装箱拆箱。
    • System.Collections.Generic.Stack<T>:泛型版本,类型安全且无性能损耗。
  • 基础操作高效
    • 入栈(Push)、出栈(Pop)、查看栈顶(Peek)的时间复杂度为 O(1) 。
(2)基础操作与示例
using System.Collections;Stack st = new Stack();
st.Push(100);      // 整数 
st.Push("Text");   // 字符串// 遍历(混合类型需类型检查)
foreach (object obj in st) {if (obj is string text) Console.WriteLine(text);
}
(3)关键注意事项
  • 线程安全:默认非线程安全,多线程需手动加锁
lock (stack) {stack.Push("concurrent_item");
}
  • 空栈操作风险:Pop()Peek() 空栈会抛异常,优先使用 TryPop()/TryPeek()(泛型)或检查 Count > 0
if (stack.TryPop(out string result)) Console.WriteLine($"出栈元素: {result}");
  • 排序与遍历限制
    • 无法直接排序,需转数组后操作(stack.ToArray().Sort())。
    • 遍历顺序为 LIFO(从栈顶到栈底)。
(4)与现代替代方案对比
特性非泛型 Stack泛型 Stack<T>ConcurrentStack<T>
类型安全❌ 需手动类型转换✅ 编译时类型检查✅ 类型安全
性能❌ 值类型需装箱拆箱✅ 无装箱拆箱,高效✅ 无锁设计,高并发优化
线程安全❌ 需手动同步❌ 需手动同步✅ 内置线程安全
推荐场景遗留代码维护、动态类型数据新项目首选(类型明确场景)高并发任务(如并行计算)
(5)典型应用场景
  • 撤销操作(Undo/Redo)
Stack<string> history = new Stack<string>();
history.Push("State1");
history.Push("State2");
string lastState = history.Pop(); // 撤销到 State1 
  • 括号匹配校验
bool IsValid(string s) {Stack<char> stack = new Stack<char>();foreach (char c in s) {if (c == '(') stack.Push(')');else if (stack.Count == 0 || stack.Pop() != c) return false;}return stack.Count == 0;
}
  • 递归函数转迭代:用栈模拟递归调用栈,避免堆栈溢出。
http://www.dtcms.com/a/461574.html

相关文章:

  • 【22.1-决策树的构建1】
  • asp制作网站wordpress使用端口
  • 【机器学习】(一)实用入门指南——如何快速搭建自己的模型
  • 【数值分析】插值法实验
  • 地方门户网站的前途搜索引擎大全全搜网
  • 如何给oracle新建架构(schema)
  • 天地数码携手一半科技PLM 赋能应对全球市场,升级热转印色带研发能力
  • 构筑智能防线:大视码垛机如何重新定义工业安全新标准
  • iPhone17实体卡槽消失?eSIM 普及下的安全挑战与应对
  • 什么RPA可以生成EXE
  • 网站开发设计jw100交换链接的作用
  • 企业推广网站建设报价吉林网站建站系统平台
  • 热壁MOCVD有助于GaN-on-AlN HEMT
  • 网站app微信三合一怎么看网站后台什么语言做的
  • 【深度学习新浪潮】大模型推理实战:模型切分核心技术(上)—— 张量并行原理+国内开源案例+踩坑点
  • 高效SQLite操作:基于C++模板元编程的自动化封装
  • uniApp App内嵌H5打开内部链接,返回手势(左滑右滑页面)会直接关闭H5项目
  • 文字排版网站网站建设的宣传词
  • K8s学习笔记(十七) pod优雅终止流程
  • Redis-基础介绍
  • Redis常用数据库及单线程模式
  • Subword-Based Tokenization策略之BPE与BBPE
  • 网站关键词用热门的还是冷门青岛天河小学网站建设
  • 个人域名备案 网站名称一元购网站建设流程图
  • 企业级灰度发布架构:基于Nginx的精细化流量治理与平滑演进实践
  • 【滑动窗口专题】第一讲:长度最小的子数组
  • 软考-系统架构设计师 基于架构的软件开发方法详细讲解
  • 电子电气架构 --- 操作系统的基本概念
  • 苏州做网站公司电话wordpress资源分享网
  • 手机能建设网站企业的做网站