C# 中的列表(List)详解
列表(List)概述
在C#中,List<T>
是System.Collections.Generic命名空间中的一个泛型集合类,它提供了动态大小的数组功能,可以存储指定类型的元素。
列表的创建与初始化
// 创建一个空列表
List<int> numbers = new List<int>();
// 创建并初始化列表
List<string> names = new List<string>() { "Alice", "Bob", "Charlie" };
// 使用容量初始化(优化性能)
List<double> values = new List<double>(100); // 初始容量为100
常用功能函数
添加元素
List<int> list = new List<int>();
// 添加单个元素
list.Add(1);
// 添加多个元素
list.AddRange(new int[] { 2, 3, 4 });
// 在指定位置插入元素
list.Insert(1, 5); // 在索引1处插入5
删除元素
// 移除指定元素(第一个匹配项)
list.Remove(3);
// 移除指定位置的元素
list.RemoveAt(0);
// 移除所有满足条件的元素
list.RemoveAll(x => x > 10);
// 清空列表
list.Clear();
查询与访问
// 获取元素数量
int count = list.Count;
// 检查是否包含某元素
bool hasFive = list.Contains(5);
// 查找元素索引
int index = list.IndexOf(4); // 返回-1如果未找到
// 使用索引器访问元素
int first = list[0];
// 查找第一个匹配条件的元素
int firstEven = list.Find(x => x % 2 == 0);
// 查找所有匹配条件的元素
List<int> allEvens = list.FindAll(x => x % 2 == 0);
排序与操作
// 排序
list.Sort();
// 自定义排序
list.Sort((a, b) => b.CompareTo(a)); // 降序排序
// 反转列表
list.Reverse();
// 转换为数组
int[] array = list.ToArray();
遍历列表
// foreach循环
foreach (var item in list)
{Console.WriteLine(item);
}// for循环
for (int i = 0; i < list.Count; i++)
{Console.WriteLine(list[i]);
}
内部存储原理
动态数组实现:List内部使用一个数组来存储元素,当元素数量超过当前数组容量时,会自动分配一个更大的数组并复制原有元素。
容量(Capacity)与数量(Count):
- Capacity:内部数组的大小
- Count:实际存储的元素数量
- 当Count达到Capacity时,Capacity会自动增长(通常是当前容量的2倍)
内存分配:
- 初始容量默认为0或4(取决于构造函数)
- 扩容操作会导致内存重新分配和元素复制,这是相对昂贵的操作
- 如果知道大致元素数量,预先设置Capacity可以提高性能
连续内存:与数组类似,List的元素在内存中是连续存储的,这提供了良好的缓存局部性。
列表(List)与数组(Array)的区别
特性 | 列表(List) | 数组(T[]) |
---|---|---|
大小 | 动态大小,自动扩展 | 固定大小,创建后不能改变 |
内存管理 | 自动管理内存,内部处理扩容 | 需要手动管理 |
性能 | 插入/删除可能触发扩容,稍慢 | 固定大小,访问速度极快 |
功能方法 | 提供丰富的方法(Add, Remove, Find等) | 基本功能,依赖Array类的静态方法 |
初始化 | 可以动态添加元素 | 创建时必须指定大小或初始化所有元素 |
内存开销 | 有少量额外开销(管理Capacity等) | 开销最小 |
适用场景 | 元素数量变化频繁的场景 | 元素数量固定或性能要求极高的场景 |
性能考虑
预分配容量:如果知道列表的大致大小,预先设置Capacity可以避免多次扩容。
List<int> list = new List<int>(1000); // 预分配1000个元素的容量
批量操作:使用AddRange比多次调用Add更高效。
频繁插入/删除:如果在列表中间频繁插入或删除元素,考虑使用LinkedList可能更合适。
只读场景:如果集合创建后不再修改,使用数组或ReadOnlyCollection可能更合适。
总结
C#中的List提供了灵活、强大的动态集合功能,它在大多数情况下可以替代数组,并提供更丰富的操作方法。理解其内部实现原理有助于编写更高效的代码,特别是在处理大量数据时。根据具体场景选择合适的数据结构(数组、列表、链表等)是编写高效C#代码的关键。