C#进阶学习(一)简单数据结构类之ArrayList、Stack、Queue、Hashtable

目录

前言

一、ArrayList(动态数组)

二、Stack(栈)

三、Queue(队列)

四、Hashtable(哈希表)

数据结构核心属性

常见API汇总表格

前言

在C#开发中,合理使用数据结构能显著提升程序性能和代码可维护性。本文将带你探索四个经典的非泛型集合类:ArrayList、Stack、Queue和Hashtable,这些类型虽然已被泛型集合取代,但理解它们的设计思想仍是进阶学习的重要基石。

一、ArrayList(动态数组)

ArrayList是一个C#为我们封装好的类
本质是一个object类型的数组
ArrayList类帮助我们实现了很多方法
比如数组的增删查改

特点:

动态扩容:自动扩展容量(初始容量4,每次翻倍)

异构存储:可混合存储任意类型对象,就是里面啥都能存,存的是object基类对象

索引访问:支持类似数组的索引器操作

增删查改操作:

cs 复制代码
ArrayList shoppingList = new ArrayList();

// ======== 增 ========
shoppingList.Add("牛奶");    // 追加元素到末尾
shoppingList.Add(3);         // 支持不同类型存储
shoppingList.Insert(1, "面包"); // 在索引1位置插入元素

// ======== 查 ========
Console.WriteLine("第一个商品:" + shoppingList[0]); // 通过索引访问
Console.WriteLine("包含牛奶吗?" + shoppingList.Contains("牛奶")); // 元素存在性检查

// ======== 改 ========
shoppingList[2] = 5; // 通过索引直接修改元素

// ======== 删 ========
shoppingList.RemoveAt(0);     // 删除指定索引元素
shoppingList.Remove(5);       // 删除首个匹配元素

// 遍历集合
foreach (var item in shoppingList)
{
//这里迭代器遍历 别也可以使用普通的for循环遍历,因为前面说了,这其实就是一个很方便的数组
    Console.WriteLine("剩余商品:" + item);
}

注意:需要引用命名空间using System.Collections;

你也可以直接将一整个数组加进去,不过加进去加的是数组里面的元素。

二、Stack(栈)

Stack是一个C#为我们封装好的类
本质也是一个object\[\]数组,只是封装了特4殊的存储规则

Stack是队列存储容器
先进后出

核心方法:

  • 核心方法:

    • Push():元素入栈

    • Pop():获取并移除栈顶元素

    • Peek():查看栈顶元素

代码示例:

你装入的是什么类型,弹出的就是什么类型。那么这种就必须你自己知道装入的是什么,非常不方便,后面我们会学习泛型,那个时候你就会发现没有泛型该多痛苦。

cs 复制代码
Stack browserHistory = new Stack();

// ======== 增 ========
browserHistory.Push("首页");    // 元素压入栈顶
browserHistory.Push("商品页");
browserHistory.Push("购物车");

// ======== 查 ========
Console.WriteLine("当前页面:" + browserHistory.Peek()); // 查看栈顶元素(不移除)

// ======== 删 ========
var currentPage = browserHistory.Pop();  // 弹出并返回栈顶元素
Console.WriteLine("离开页面:" + currentPage);

/* 
注意:栈结构不支持直接修改中间元素
所有操作只能在栈顶进行
*/

注意:

需要使用System.Collections命名空间

三、Queue(队列)

Quene是一个C#为我们封装好的类
本质也是一个object\[\]数组,只是封装了特殊的存储规则

Quene是队列存储容器
先进先出

代码示例:

cs 复制代码
Queue printerQueue = new Queue();

// ======== 增 ========
printerQueue.Enqueue("简历.pdf");  // 元素加入队尾
printerQueue.Enqueue("报告.doc");
printerQueue.Enqueue("照片.jpg");

// ======== 查 ========
Console.WriteLine("下一个文件:" + printerQueue.Peek()); // 查看队首元素(不移除)

// ======== 删 ========
while(printerQueue.Count > 0)
{
    var file = printerQueue.Dequeue();  // 移除并返回队首元素
    Console.WriteLine("正在打印:" + file);
}

/*
注意:队列结构不支持直接修改中间元素
遵循先进先出原则操作
*/

注意:

需要使用System.Collections命名空间

四、Hashtable(哈希表)

Hashtable又称散列表 是基于键的哈希代码组织起来的 键/值对集合
它的主要作用是提高数据查询的效率
使用键来访问集合中的元素

代码示例:

cs 复制代码
Hashtable countryCodes = new Hashtable();

// ======== 增 ========
countryCodes.Add("CN", "中国");  // 添加键值对
countryCodes["US"] = "美国";     // 通过索引器添加
countryCodes["JP"] = "日本";

// ======== 查 ========
if(countryCodes.ContainsKey("CN"))  // 检查键是否存在
{
    Console.WriteLine("CN对应:" + countryCodes["CN"]); // 通过键查找值
}

// ======== 改 ========
countryCodes["US"] = "美利坚合众国";  // 通过索引器修改值

// ======== 删 ========
countryCodes.Remove("JP");  // 根据键删除条目

// 遍历键值对
foreach(DictionaryEntry entry in countryCodes)
{
    Console.WriteLine($"键:{entry.Key},值:{entry.Value}");
}

注意:

需要引用命名空间:using System.Collections;

总结:

数据结构核心属性

数据结构 关键属性 说明
ArrayList Count 当前实际存储的元素数量
Capacity 当前分配的存储容量(当Count超过时自动扩容)
Stack Count 栈中元素个数
Queue Count 队列中元素个数
Hashtable Count 键值对数量
Keys 包含所有键的ICollection集合
Values 包含所有值的ICollection集合

常见API汇总表格

数据结构 方法名 功能描述
ArrayList Add(object value) 添加元素到列表末尾
Insert(int index, object value) 在指定位置插入元素
Remove(object obj) 删除第一个匹配元素
RemoveAt(int index) 删除指定索引元素
Contains(object obj) 检查元素是否存在
Stack Push(object obj) 元素压入栈顶
Pop() 移除并返回栈顶元素
Peek() 查看栈顶元素(不移除)
Queue Enqueue(object obj) 元素加入队尾
Dequeue() 移除并返回队首元素
Peek() 查看队首元素(不移除)
Hashtable Add(object key, object value) 添加键值对
Remove(object key) 根据键删除条目
ContainsKey(object key) 检查键是否存在
ContainsValue(object value) 检查值是否存在

ArrayList与普通数组的本质区别

普通数组 是固定大小的连续内存空间,在声明时必须指定长度且不可更改。它支持快速随机访问,但缺乏动态调整能力,且只能存储单一类型元素(在C#中是类型安全的)。ArrayList本质上是一个动态包装的Object数组,通过以下特性突破普通数组的限制:

  1. 动态扩容:当元素数量超过当前容量时,自动创建新数组并复制元素(默认扩容策略:容量翻倍)

  2. 类型混合:由于存储Object类型元素,可以混合存放不同数据类型

  3. 丰富操作:提供插入、删除、搜索等内置方法,无需手动实现

  4. 容量管理 :通过Capacity属性显式控制底层数组大小,平衡性能与内存

代价是:

  • 值类型存储时会产生装箱拆箱开销

  • 读取元素时需要强制类型转换

  • 自动扩容时存在内存复制消耗

相关推荐
inrichtt6 小时前
第八课时:SPI总线揭秘:四线全双工通信的奥
c语言·数据结构·stm32·单片机·嵌入式硬件
HPtiger7 小时前
数据结构——选择排序
数据结构·算法·排序算法
丑梨数据7 小时前
信创环境里跑文档工具:格式兼容与本地合规的几个坑
数据结构·人工智能·算法·决策树·排序算法
烂蜻蜓7 小时前
Pandas入门教程(四):Series数据结构——创建、索引与常用方法
数据结构·pandas
星恒随风9 小时前
Linux线程概念详解:从分页存储、页表、MMU与TLB,深入理解线程和进程的区别与联系
linux·运维·笔记·学习·状态模式
qq_284274059 小时前
数控机床编程基础与坐标系:编程六步流程、程序号/程序段/程序字格式,与右手定则下车床铣床XYZ轴判定(含考点)
笔记·学习·自动化·制造
德林恩宝9 小时前
On-Policy Distillation(OPD)学习文档
人工智能·学习·机器学习·大模型·llm·大模型微调
xxwl58510 小时前
区域赛分类题解
c++·笔记·学习·算法
用户7884773163412 小时前
用 C# 把每周 6 小时的 PDF 录入干到 20 分钟:一份可复制的桌面 OCR 方案
c#
csdn_aspnet13 小时前
C# .NetCore Swagger ISchemaFilter 处理枚举、特殊类型
c#·.netcore·swagger