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>等并发集合。
