308 lines
6.0 KiB
Markdown
308 lines
6.0 KiB
Markdown
|
|
# ArrayList
|
|||
|
|
概念:
|
|||
|
|
`ArrayList` 是 C# 提供的一个==非泛型集合类==
|
|||
|
|
本质上可以理解成:==一个长度可变的 `object` 数组==
|
|||
|
|
|
|||
|
|
它可以:
|
|||
|
|
1. 像数组一样按下标访问
|
|||
|
|
2. 自动扩容
|
|||
|
|
3. 增删查改元素
|
|||
|
|
4. 存储任意类型的对象
|
|||
|
|
|
|||
|
|
命名空间:
|
|||
|
|
```csharp
|
|||
|
|
using System.Collections;
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
注意:
|
|||
|
|
是 `System.Collections`
|
|||
|
|
不是 `System.Collection`
|
|||
|
|
|
|||
|
|
----
|
|||
|
|
# 通常用法
|
|||
|
|
1. 学习 C# 早期非泛型集合
|
|||
|
|
2. 理解 `object`、装箱和拆箱
|
|||
|
|
3. 存储数量不固定的数据
|
|||
|
|
4. 对数组进行更方便的增删操作
|
|||
|
|
|
|||
|
|
实际开发中:
|
|||
|
|
新代码更推荐使用 `List<T>`
|
|||
|
|
`ArrayList` 主要作为进阶阶段理解集合历史和装箱拆箱的材料
|
|||
|
|
|
|||
|
|
----
|
|||
|
|
# 语法
|
|||
|
|
创建:
|
|||
|
|
```csharp
|
|||
|
|
ArrayList list = new ArrayList();
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
添加:
|
|||
|
|
```csharp
|
|||
|
|
list.Add(数据);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
访问:
|
|||
|
|
```csharp
|
|||
|
|
list[下标]
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
长度:
|
|||
|
|
```csharp
|
|||
|
|
list.Count
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
----
|
|||
|
|
# 基础案例
|
|||
|
|
```csharp
|
|||
|
|
using System;
|
|||
|
|
using System.Collections;
|
|||
|
|
|
|||
|
|
ArrayList list = new ArrayList();
|
|||
|
|
|
|||
|
|
list.Add("小明");
|
|||
|
|
list.Add(18);
|
|||
|
|
list.Add(true);
|
|||
|
|
|
|||
|
|
Console.WriteLine(list[0]);
|
|||
|
|
Console.WriteLine(list[1]);
|
|||
|
|
Console.WriteLine(list[2]);
|
|||
|
|
Console.WriteLine(list.Count);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
理解:
|
|||
|
|
1. `ArrayList` 内部存的是 `object`
|
|||
|
|
2. 所以字符串、整数、布尔值都可以放进去
|
|||
|
|
3. `Count` 表示当前实际存了多少个元素
|
|||
|
|
|
|||
|
|
----
|
|||
|
|
# 增删查改
|
|||
|
|
增加:
|
|||
|
|
```csharp
|
|||
|
|
ArrayList list = new ArrayList();
|
|||
|
|
|
|||
|
|
list.Add("A");
|
|||
|
|
list.Add("B");
|
|||
|
|
list.Insert(1, "C");
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
结果:
|
|||
|
|
```text
|
|||
|
|
A C B
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
删除:
|
|||
|
|
```csharp
|
|||
|
|
list.Remove("A"); // 删除第一个匹配的元素
|
|||
|
|
list.RemoveAt(0); // 删除指定下标的元素
|
|||
|
|
list.Clear(); // 清空所有元素
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
查找:
|
|||
|
|
```csharp
|
|||
|
|
bool hasB = list.Contains("B");
|
|||
|
|
int index = list.IndexOf("B");
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
修改:
|
|||
|
|
```csharp
|
|||
|
|
list[0] = "新的值";
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
----
|
|||
|
|
# 遍历
|
|||
|
|
使用 `for`:
|
|||
|
|
```csharp
|
|||
|
|
ArrayList list = new ArrayList();
|
|||
|
|
list.Add("A");
|
|||
|
|
list.Add("B");
|
|||
|
|
list.Add("C");
|
|||
|
|
|
|||
|
|
for (int i = 0; i < list.Count; i++)
|
|||
|
|
{
|
|||
|
|
Console.WriteLine(list[i]);
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
使用 `foreach`:
|
|||
|
|
```csharp
|
|||
|
|
foreach (object item in list)
|
|||
|
|
{
|
|||
|
|
Console.WriteLine(item);
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
因为 `ArrayList` 中的元素都是按 `object` 看待,所以 `foreach` 变量常写成 `object`。
|
|||
|
|
|
|||
|
|
----
|
|||
|
|
# 取值时要类型转换
|
|||
|
|
```csharp
|
|||
|
|
ArrayList list = new ArrayList();
|
|||
|
|
list.Add(100);
|
|||
|
|
|
|||
|
|
int num = (int)list[0];
|
|||
|
|
Console.WriteLine(num);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
原因:
|
|||
|
|
`list[0]` 的返回类型是 `object`
|
|||
|
|
如果要当成 `int` 使用,就需要拆箱 / 强制类型转换
|
|||
|
|
|
|||
|
|
错误示意:
|
|||
|
|
```csharp
|
|||
|
|
int num = list[0];
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
这样会报错,因为不能把 `object` 直接赋值给 `int`。
|
|||
|
|
|
|||
|
|
----
|
|||
|
|
# 装箱和拆箱问题
|
|||
|
|
```csharp
|
|||
|
|
ArrayList list = new ArrayList();
|
|||
|
|
|
|||
|
|
int hp = 100;
|
|||
|
|
list.Add(hp); // int 放进 object,发生装箱
|
|||
|
|
|
|||
|
|
int value = (int)list[0]; // object 取回 int,发生拆箱
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
理解:
|
|||
|
|
1. 值类型放进 `ArrayList` 时,会发生装箱
|
|||
|
|
2. 从 `ArrayList` 取出值类型时,需要拆箱
|
|||
|
|
3. 装箱和拆箱都有额外开销
|
|||
|
|
4. 类型转错还会运行时报错
|
|||
|
|
|
|||
|
|
这个点可以和[[万物之父和装箱与拆箱|装箱与拆箱]]一起理解。
|
|||
|
|
|
|||
|
|
----
|
|||
|
|
# Capacity 和 Count
|
|||
|
|
`Count`:
|
|||
|
|
当前实际有多少个元素
|
|||
|
|
|
|||
|
|
`Capacity`:
|
|||
|
|
内部数组当前能容纳多少个元素
|
|||
|
|
|
|||
|
|
```csharp
|
|||
|
|
ArrayList list = new ArrayList();
|
|||
|
|
|
|||
|
|
Console.WriteLine(list.Count);
|
|||
|
|
Console.WriteLine(list.Capacity);
|
|||
|
|
|
|||
|
|
list.Add("A");
|
|||
|
|
list.Add("B");
|
|||
|
|
|
|||
|
|
Console.WriteLine(list.Count);
|
|||
|
|
Console.WriteLine(list.Capacity);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
理解:
|
|||
|
|
`ArrayList` 内部会自动扩容
|
|||
|
|
`Count` 是实际数量
|
|||
|
|
`Capacity` 是容量,不一定等于数量
|
|||
|
|
|
|||
|
|
----
|
|||
|
|
# 排序和反转
|
|||
|
|
排序:
|
|||
|
|
```csharp
|
|||
|
|
ArrayList list = new ArrayList();
|
|||
|
|
list.Add(3);
|
|||
|
|
list.Add(1);
|
|||
|
|
list.Add(2);
|
|||
|
|
|
|||
|
|
list.Sort();
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
反转:
|
|||
|
|
```csharp
|
|||
|
|
list.Reverse();
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
注意:
|
|||
|
|
如果里面混放了不能互相比较的类型,`Sort()` 可能会出错
|
|||
|
|
|
|||
|
|
例如:
|
|||
|
|
```csharp
|
|||
|
|
list.Add(10);
|
|||
|
|
list.Add("A");
|
|||
|
|
list.Sort(); // 可能出错
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
所以虽然 `ArrayList` 可以存任意类型,但最好不要随便混放。
|
|||
|
|
|
|||
|
|
----
|
|||
|
|
# 和数组的区别
|
|||
|
|
| 对比点 | 数组 | ArrayList |
|
|||
|
|
| ---- | --------- | -------------- |
|
|||
|
|
| 长度 | 创建后固定 | 可以动态增删 |
|
|||
|
|
| 类型 | 通常固定一种类型 | 内部按 `object` 存 |
|
|||
|
|
| 访问 | 可以用下标 | 可以用下标 |
|
|||
|
|
| 性能 | 类型明确,性能较好 | 可能有装箱拆箱 |
|
|||
|
|
| 常用程度 | 基础常用 | 现在新项目较少用 |
|
|||
|
|
|
|||
|
|
----
|
|||
|
|
# 常见错误
|
|||
|
|
错误1:忘记引用命名空间
|
|||
|
|
```csharp
|
|||
|
|
ArrayList list = new ArrayList();
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
解决:
|
|||
|
|
```csharp
|
|||
|
|
using System.Collections;
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
----
|
|||
|
|
错误2:取值时忘记强转
|
|||
|
|
```csharp
|
|||
|
|
ArrayList list = new ArrayList();
|
|||
|
|
list.Add(10);
|
|||
|
|
|
|||
|
|
int num = list[0];
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
应该写:
|
|||
|
|
```csharp
|
|||
|
|
int num = (int)list[0];
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
----
|
|||
|
|
错误3:混放类型后强转错误
|
|||
|
|
```csharp
|
|||
|
|
ArrayList list = new ArrayList();
|
|||
|
|
list.Add("100");
|
|||
|
|
|
|||
|
|
int num = (int)list[0];
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
`list[0]` 实际是字符串,不是整数,会出错。
|
|||
|
|
|
|||
|
|
----
|
|||
|
|
# 注意
|
|||
|
|
1. `ArrayList` 在 `System.Collections` 命名空间中
|
|||
|
|
2. `ArrayList` 是非泛型集合,内部按 `object` 存储
|
|||
|
|
3. 它可以动态增删元素
|
|||
|
|
4. 取出元素时通常需要强制类型转换
|
|||
|
|
5. 值类型放入 `ArrayList` 会发生装箱
|
|||
|
|
6. 不建议随意混放不同类型,容易产生转换错误
|
|||
|
|
7. 新项目通常优先使用 `List<T>`,类型更安全
|
|||
|
|
|
|||
|
|
----
|
|||
|
|
# 一句话记忆
|
|||
|
|
==ArrayList 是会自动扩容的 object 数组,方便但不够类型安全。==
|
|||
|
|
|
|||
|
|
----
|
|||
|
|
# 面试/复习时怎么说
|
|||
|
|
可以这样答:
|
|||
|
|
|
|||
|
|
“ArrayList 是 `System.Collections` 命名空间下的非泛型集合,本质上可以理解为动态扩容的 `object` 数组。
|
|||
|
|
它可以存储任意类型,但取值时通常需要强制类型转换,值类型放进去还会发生装箱。
|
|||
|
|
所以它适合用来理解非泛型集合和装箱拆箱,新项目中一般更推荐使用泛型集合 `List<T>`。”
|
|||
|
|
|
|||
|
|
----
|
|||
|
|
引用:
|
|||
|
|
1. Microsoft Learn: [ArrayList Class](https://learn.microsoft.com/en-us/dotnet/api/system.collections.arraylist?view=net-9.0)
|
|||
|
|
2. Microsoft Learn: [System.Collections Namespace](https://learn.microsoft.com/en-us/dotnet/api/system.collections?view=net-9.0)
|
|||
|
|
|
|||
|
|
#ArrayList
|
|||
|
|
#集合
|
|||
|
|
#进阶
|