c#泛型集合(ArrayList和List、Dictionary的对比)
·
一、List<T> 集合
1. 基本概念
-
泛型集合:只能存储指定类型的数据,类型安全。
-
动态扩容:无需指定初始大小,自动调整容量。
-
性能优势:避免装箱拆箱(相比
ArrayList)。
2. 创建与初始化
// 空列表
List<int> list = new List<int>();
// 带初始值的列表
List<string> list4 = new List<string> { "aaa", "ccc", "bbb" };
3. 常用属性与方法
| 操作 | 代码示例 | 说明 |
|---|---|---|
| 添加元素 | list.Add(100); |
在末尾添加单个元素。 |
| 批量添加 | list.AddRange(new[] {1, 2, 3}); |
添加集合中的所有元素。 |
| 插入元素 | list.Insert(1, "apple"); |
在指定索引处插入元素。 |
| 访问元素 | string item = list[0]; |
通过索引访问元素(索引从 0 开始)。 |
| 修改元素 | list[0] = "banana"; |
通过索引修改元素值。 |
| 删除元素 | list.Remove("apple"); |
删除第一个匹配的元素。 |
| 删除指定位置 | list.RemoveAt(0); |
删除指定索引的元素。 |
| 判断元素存在 | bool exists = list.Contains("apple"); |
检查列表是否包含指定元素。 |
| 获取元素索引 | int index = list.IndexOf("apple"); |
返回元素的第一个索引(不存在返回 -1)。 |
| 排序 | list.Sort(); |
对列表进行升序排序(元素需实现 IComparable)。 |
| 反转顺序 | list.Reverse(); |
反转列表元素的顺序。 |
| 清空列表 | list.Clear(); |
移除所有元素。 |
| 获取元素数量 | int count = list.Count; |
返回列表中的元素个数。 |
4. 高阶函数(Lambda 表达式)
| 方法 | 作用 | 示例 |
|---|---|---|
Find() |
查找第一个符合条件的元素。 | int evenNum = list.Find(x => x % 2 == 0); |
FindAll() |
查找所有符合条件的元素,返回新列表。 | List<int> evens = list.FindAll(x => x % 2 == 0); |
FindIndex() |
查找第一个符合条件的元素的索引。 | int index = list.FindIndex(x => x > 10); |
Any() |
判断是否存在符合条件的元素(返回 bool)。 |
bool hasEven = list.Any(x => x % 2 == 0); |
All() |
判断所有元素是否都符合条件。 | bool allPositive = list.All(x => x > 0); |
Where() |
筛选符合条件的元素(返回 IEnumerable<T>)。 |
var filtered = list.Where(x => x < 100); |
ForEach() |
对每个元素执行操作。 | list.ForEach(x => Console.WriteLine(x)); |
二、Dictionary<TKey, TValue> 字典
1. 基本概念
-
键值对集合:每个元素包含唯一的键(
Key)和对应的值(Value)。 -
快速查找:通过键快速定位值(时间复杂度 O (1))。
-
键的唯一性:键不能重复,且必须实现
IEquatable<T>接口。
2. 创建与初始化
// 空字典
Dictionary<string, int> dict = new Dictionary<string, int>();
// 带初始值的字典
Dictionary<string, int> asciiDict = new Dictionary<string, int> {
{"a", 97},
{"c", 99},
{"b", 98}
};
3. 常用属性与方法
| 操作 | 代码示例 | 说明 |
|---|---|---|
| 添加键值对 | dict.Add("apple", 1); |
添加键值对(键不存在时)。 |
| 通过键访问值 | int value = dict["apple"]; |
通过键获取值(键不存在时抛出异常)。 |
| 通过键设置值 | dict["apple"] = 100; |
修改已存在键对应的值。 |
| 安全获取值 | bool found = dict.TryGetValue("apple", out int value); |
尝试获取值,避免异常。 |
| 判断键是否存在 | bool hasKey = dict.ContainsKey("apple"); |
检查字典是否包含指定键。 |
| 判断值是否存在 | bool hasValue = dict.ContainsValue(1); |
检查字典是否包含指定值。 |
| 删除键值对 | dict.Remove("apple"); |
删除指定键对应的元素。 |
| 清空字典 | dict.Clear(); |
移除所有键值对。 |
| 获取所有键 | var keys = dict.Keys; |
返回所有键的集合(类型:Dictionary<TKey, TValue>.KeyCollection)。 |
| 获取所有值 | var values = dict.Values; |
返回所有值的集合(类型:Dictionary<TKey, TValue>.ValueCollection)。 |
| 获取元素数量 | int count = dict.Count; |
返回字典中键值对的数量。 |
4. 遍历字典
// 遍历所有键值对
foreach (KeyValuePair<string, int> item in dict) {
Console.WriteLine($"Key: {item.Key}, Value: {item.Value}");
}
// 简化写法(使用 var)
foreach (var item in dict) {
Console.WriteLine($"Key: {item.Key}, Value: {item.Value}");
}
// 单独遍历键或值
foreach (string key in dict.Keys) {
Console.WriteLine(key);
}
foreach (int value in dict.Values) {
Console.WriteLine(value);
}
三、List<T> 与 ArrayList 的对比
| 特性 | List<T> | ArrayList |
|---|---|---|
| 类型安全 | 是(泛型) | 否(可存储任意类型) |
| 装箱拆箱 | 无 | 有(值类型与 object 之间转换) |
| 性能 | 高(无需类型转换) | 低(频繁装箱拆箱) |
| 语法 | 需要指定类型 List<int> |
直接使用 ArrayList |
| 推荐场景 | 存储相同类型的数据 | 需存储混合类型(不推荐) |
四、代码补充建议
1. List<T> 补充
// 安全访问元素(避免索引越界)
if (index < list.Count) {
Console.WriteLine(list[index]);
}
// 使用 List<T> 的构造函数初始化
List<int> numbers = new List<int>(new[] {1, 2, 3});
// 复杂对象的列表
List<Person> people = new List<Person> {
new Person { Name = "Alice", Age = 30 },
new Person { Name = "Bob", Age = 25 }
};
// 对复杂对象排序
people.Sort((p1, p2) => p1.Age.CompareTo(p2.Age));
2. Dictionary<TKey, TValue> 补充
// 安全添加键值对(避免键已存在的异常)
if (!dict.ContainsKey("apple")) {
dict.Add("apple", 1);
}
// 或者使用 TryAdd(.NET Core 2.0+)
dict.TryAdd("apple", 1);
// 嵌套字典
Dictionary<string, Dictionary<string, int>> nestedDict = new Dictionary<string, Dictionary<string, int>>();
nestedDict["fruits"] = new Dictionary<string, int> { {"apple", 1}, {"banana", 2} };
五、注意事项
-
集合线程安全:
List<T>和Dictionary<TKey, TValue>是非线程安全的。多线程环境下使用需加锁或使用ConcurrentDictionary<TKey, TValue>。 -
键的唯一性:字典的键必须唯一,否则会抛出
ArgumentException。 -
空引用检查:访问集合元素前建议检查
Count > 0或使用Any()方法。 -
性能优化:若需频繁插入 / 删除元素,考虑使用
LinkedList<T>;若需线程安全,使用ConcurrentBag<T>等并发集合。
更多推荐


所有评论(0)