C#集合:ArrayList、Queue、Stack
数组不够用的时候,我发现了这些更好用的集合
前言
学完数组之后,我一直觉得有个地方不太舒服:数组的长度是固定的。
比如我声明了一个长度为5的数组,结果突然要多存一个数据,怎么办?没法办,只能重新建一个更大的数组,再把原来的数据复制过去...太麻烦了。
后来我学到了集合,这个问题终于解决了。
一、为什么我不想再用数组了?
数组确实简单直接,但它的限制也很明显:
-
长度固定:一开始说好存5个,就只能存5个
-
类型单一:声明成int数组,就只能存整数
-
增删麻烦:想在中间插一个元素?自己写代码移位吧
直到我遇到了ArrayList,才发现原来可以这么方便。
二、ArrayList:我最先学会的集合
2.1 它是什么?
ArrayList可以理解成一个“会自动长大的数组”。你不用告诉它该多大,往里放东西就行,放不下了它会自己扩容。
用之前记得加上:
using System.Collections;
2.2 我喜欢的几个操作
随便往里放东西:
ArrayList list = new ArrayList();
// 啥类型都能放,这点太爽了
list.Add(1); // 整数
list.Add("你好"); // 字符串
list.Add(true); // 布尔值
插入和删除都很简单:
// 在指定位置插入
list.Insert(1, "插在这里");
// 删除某个元素
list.Remove("你好");
// 删除某个位置的元素
list.RemoveAt(0);
// 一键清空
list.Clear();
查找也很方便:
// 看看有没有这个元素
if (list.Contains(1))
{
Console.WriteLine("存在");
}
// 看看现在有几个元素
int count = list.Count;
2.3 我踩过的一个坑
ArrayList虽然方便,但它取出来的数据默认是object类型。我存了个整数进去,取出来要转回整数才能用。
ArrayList list = new ArrayList();
list.Add(100);
// 必须转型,不然会报错
int num = (int)list[0];
老师说这叫拆箱,后面学了泛型就可以避免这个问题了。
三、Queue:我理解的“排队”
3.1 队列是什么?
Queue就是队列,跟排队买奶茶一样:先来的人先买到,后来的人排后面。
计算机术语叫FIFO(先进先出)。
3.2 什么时候用队列?
老师举了几个例子,我觉得很好理解:
-
打印机任务:先提交的文档先打印
-
客服排队:先排队的用户先接入
-
消息处理:先来的消息先处理
3.3 基本用法
存数据(入队):
Queue queue = new Queue();
queue.Enqueue("第一个人");
queue.Enqueue("第二个人");
queue.Enqueue("第三个人");
// 队列里:第一个人 → 第二个人 → 第三个人
取数据(出队):
// 取出并删除队首
string first = queue.Dequeue(); // 得到"第一个人"
// 现在队列只剩:第二个人 → 第三个人
// 只看不取(不删除)
string peek = queue.Peek(); // 得到"第二个人",队列不变
其他常用操作:
// 看看有没有某个人
bool exists = queue.Contains("第二个人");
// 看看队伍多长
int count = queue.Count;
// 队伍解散
queue.Clear();
四、Stack:我理解的“叠盘子”
4.1 栈是什么?
Stack就是栈,像叠盘子一样:后放上去的盘子,会先被拿下来。
计算机术语叫LIFO(后进先出)。
4.2 什么时候用栈?
老师举的例子我也记住了:
-
浏览器后退:最后访问的页面最先退回
-
Ctrl+Z撤销:最后做的操作最先撤销
-
叠盘子:后放的先拿
4.3 基本用法
存数据(入栈):
Stack stack = new Stack();
stack.Push("第一个");
stack.Push("第二个");
stack.Push("第三个");
// 栈顶是"第三个"
取数据(出栈):
// 取出并删除栈顶
string top = stack.Pop(); // 得到"第三个"
// 现在栈里:第一个 → 第二个(第二个在顶部)
// 只看不取
string peek = stack.Peek(); // 得到"第二个",栈不变
其他操作:
// 看看有没有
bool exists = stack.Contains("第一个");
// 看看有几个
int count = stack.Count;
// 清空
stack.Clear();
五、我做的对比总结
学完这三个,我整理了一个表格方便记忆:
| 特性 | ArrayList | Queue | Stack |
|---|---|---|---|
| 外号 | 万能容器 | 排队 | 叠盘子 |
| 原则 | 按位置存取 | 先进先出 | 后进先出 |
| 取数据 | 通过索引 | 只能取队首 | 只能取栈顶 |
| 中间插入 | 可以 | 不行 | 不行 |
我的选择指南:
-
需要随便存随便取 → ArrayList
-
模拟排队、任务处理 → Queue
-
撤销操作、后退功能 → Stack
六、老师还提了一嘴泛型
老师说上面的ArrayList、Queue、Stack是非泛型集合,可以存任何类型,但也正因为这样,取出来需要转型。
后来微软推出了泛型版本,可以限定只能存一种类型:
| 非泛型 | 泛型版本 | 说明 |
|---|---|---|
| ArrayList | List<T> | 只能存指定类型 |
| Queue | Queue<T> | 只能存指定类型 |
| Stack | Stack<T> | 只能存指定类型 |
// 泛型版本示例
List<int> numbers = new List<int>(); // 只能存int
numbers.Add(1);
// numbers.Add("abc"); // 这行会报错,存不了
泛型版本取数据不用转型,更安全,老师说以后会重点讲。
写在最后
学完集合之后,我写代码舒服多了。不用再纠结数组长度不够的问题,增删改查也有现成的方法。
一句话记住它们:
-
ArrayList = 想存啥存啥的动态数组
-
Queue = 先来后到的排队
-
Stack = 后来居上的叠盘子
更多推荐



所有评论(0)