经常使用List,总结一些List的一些实用方法


一、基础操作

1. 添加元素

  • Add(T item):在列表末尾添加一个元素。
    List<string> fruits = new List<string>();
    fruits.Add("Apple");
    
  • AddRange(IEnumerable<T> collection):添加集合中的所有元素。
    fruits.AddRange(new[] { "Banana", "Cherry" });
    

2. 插入元素

  • Insert(int index, T item):在指定索引处插入元素。
    fruits.Insert(1, "Mango"); // 在索引1处插入
    
  • InsertRange(int index, IEnumerable<T> collection):在指定索引处插入集合。

3. 删除元素

  • Remove(T item):删除第一个匹配的元素,返回是否成功。
    bool removed = fruits.Remove("Apple");
    
  • RemoveAt(int index):删除指定索引的元素。
    fruits.RemoveAt(0); // 删除第一个元素
    
  • RemoveAll(Predicate<T> match):删除所有符合条件的元素。
    fruits.RemoveAll(f => f.Length < 5); // 删除长度小于5的元素
    
  • RemoveRange(int index, int count):删除指定范围内的元素。

4. 查找元素

  • Contains(T item):判断列表是否包含某个元素(使用 Equals 比较)。
    bool hasApple = fruits.Contains("Apple");
    
  • IndexOf(T item)LastIndexOf(T item):查找元素首次/最后一次出现的索引。
    int index = fruits.IndexOf("Banana"); // 找不到返回-1
    
  • Find(Predicate<T> match)FindLast(Predicate<T> match):查找第一个/最后一个符合条件的元素。
    string longName = fruits.Find(f => f.Length > 6);
    
  • FindIndex(Predicate<T> match)FindLastIndex(Predicate<T> match):查找符合条件的元素的索引。

二、高级查询(LINQ扩展)

虽然这些是扩展方法(不是 List<T> 自身的方法),但非常实用:

  • Where(Func<T, bool> predicate):筛选符合条件的元素。
    var filtered = fruits.Where(f => f.StartsWith("A"));
    
  • OrderBy(Func<T, K> keySelector)OrderByDescending:排序。
    var sorted = fruits.OrderBy(f => f.Length);
    
  • First(Func<T, bool> predicate)FirstOrDefault:获取第一个符合条件的元素(或默认值)。
    string first = fruits.First(f => f.Contains("a"));
    
  • Single(Func<T, bool> predicate)SingleOrDefault:获取唯一符合条件的元素(或默认值)。
  • Select(Func<T, TResult> selector):投影元素到新类型。
    var lengths = fruits.Select(f => f.Length);
    

三、列表操作

  • Sort():对列表进行原地排序(默认比较器或自定义比较器)。
    fruits.Sort(); // 按字母排序
    fruits.Sort((x, y) => y.Length.CompareTo(x.Length)); // 按长度降序
    
  • Reverse():反转列表元素的顺序。
    fruits.Reverse();
    
  • Take(int count)Skip(int count):截取或跳过指定数量的元素(用于分页)。
    var page1 = fruits.Take(10);
    var page2 = fruits.Skip(10).Take(10);
    
  • Distinct():获取列表中的不重复元素。
    var uniqueFruits = fruits.Distinct().ToList();
    
  • ConvertAll<TOutput>(Converter<T, TOutput> converter):转换列表元素类型。
    List<int> lengths = fruits.ConvertAll(f => f.Length);
    

四、性能优化

  • Capacity 属性:设置或获取列表的容量(预分配空间,减少扩容次数)。
    List<int> numbers = new List<int>(100); // 预分配100个元素的空间
    
  • TrimExcess():将容量调整为实际元素数量(释放多余内存)。
    numbers.TrimExcess();
    

五、判断与转换

  • TrueForAll(Predicate<T> match):判断所有元素是否都满足条件。
    bool allLong = fruits.TrueForAll(f => f.Length > 3);
    
  • Exists(Predicate<T> match):判断是否存在至少一个满足条件的元素。
    bool hasLongName = fruits.Exists(f => f.Length > 10);
    
  • ToArray():将列表转换为数组。
    string[] array = fruits.ToArray();
    
  • AsReadOnly():返回列表的只读包装。
    ReadOnlyCollection<string> readOnly = fruits.AsReadOnly();
    

六、批量操作

  • ForEach(Action<T> action):对每个元素执行操作。
    fruits.ForEach(f => Console.WriteLine(f.ToUpper()));
    
  • FindAll(Predicate<T> match):获取所有符合条件的元素。
    var apples = fruits.FindAll(f => f.Contains("apple"));
    
  • GetRange(int index, int count):获取指定范围的元素。
    var subset = fruits.GetRange(2, 3); // 从索引2开始取3个元素
    

注意事项

  1. 线程安全List<T> 不是线程安全的。多线程环境下使用 ConcurrentBag<T> 或手动同步。
  2. 性能考虑
    • 频繁插入/删除元素:考虑使用 LinkedList<T>
    • 频繁查找:考虑使用 Dictionary<TKey, TValue> 或先排序再使用二分查找。
  3. 空引用处理:使用 FirstOrDefault/SingleOrDefault 时注意检查返回值是否为 null

总结

根据需求选择合适的方法:

  • 增删改查AddRemoveFindIndexOf
  • 筛选排序WhereOrderBySort
  • 分页截取TakeSkip
  • 性能优化CapacityTrimExcess