Skip to content

C# - List<T>

List<T> 是一个强类型对象的集合,可以通过索引访问,并具有排序、搜索和修改列表的方法。 它是 System.Collection.Generic 命名空间下的 ArrayList 的泛型版本。 有了这个之后我们基本不在用ArrayList了。

List<T> 特征

  • List<T> 等效于 ArrayList,它实现了 IList<T>。
  • 它位于 System.Collections.Generic 命名空间下。
  • List<T> 可以包含指定类型的元素。 它提供编译时类型检查并且不执行装箱拆箱,因为它是通用的。
  • 可以使用 Add()、AddRange() 方法或集合初始值设定项语法添加元素。
  • 可以通过传递索引来访问元素,例如 我的列表[0]。 索引从零开始。
  • List<T> 比 ArrayList 执行得更快,更不容易出错。

创建一个List Creating a List

List<T> 是一个泛型集合,因此您需要为其可以存储的数据类型指定一个类型参数。 以下示例展示如何创建列表和添加元素。

csharp
  static void Main(string[] args)
        {
            var numberList = new List<int>();
            numberList.Add(1); // 通用 add添加元素
            numberList.Add(3);
            numberList.Add(5);
            numberList.Add(7);

            var cities = new List<string>();
            cities.Add("北京");
            cities.Add("广州");
            cities.Add("上海");
            cities.Add("厦门");
            cities.Add(null); // null是允许的

            // 使用 集合初始值设定项 语法来添加元素 
            var bigCities = new List<string>()
                    {
                        "北京",
                        "广州",
                        "上海",
                        "厦门"
                    };
        }

在上面的例子中,我们使用 var numberList = new List<int>(); 来创建一个 int 类型的集合。 同样,我们也创建了cities 和 bigCities 都是字符串类型集合。 然后,您可以使用 Add() 方法或集合初始值设定项语法在列表中添加元素。

您还可以使用集合初始值设定项语法添加自定义类的元素。 下面在List<Student>中添加Student类的对象。

csharp
public class Student
{
    public int Id { get; set; }

    public string Name { get; set; }

}
class Program
{
    static void Main(string[] args)
    {
        var students = new List<Student>() 
        {
            new Student(){ Id = 1, Name="Ma"},
            new Student(){ Id = 2, Name="Le"},
            new Student(){ Id = 3, Name="Ma2"},
            new Student(){ Id = 4, Name="Hello"}
        };

    }
}

添加一组数据到list当中

使用 AddRange(IEnumerable<T> collection) 方法将数组或其他集合中的所有元素添加到 List。

csharp
        static void Main(string[] args)
        {
            var names = new List<string> { "baidu", "qq", "malema" };

            var popularNames = new List<string>();

            popularNames.AddRange(names);
        }

访问List元素

可以通过索引、for/foreach 循环和使用 LINQ 查询访问List。 List的索引从零开始。 与数组相同可以通过索引器来访问单个元素。 也可以使用 foreach 或 for 循环迭代 List<T> 集合。

csharp
 var names = new List<string> { "baidu", "qq", "malema" };
            var popularNames = new List<string>();
            popularNames.AddRange(names);
            Console.WriteLine(names[0]); //baidu
            Console.WriteLine(names[1]); //qq
            foreach (var item in popularNames)
            {
                Console.WriteLine(item);
            }
            popularNames.ForEach(it => Console.WriteLine(it));

            for (int i = 0; i < names.Count; i++)
                Console.WriteLine(names[i]); //省略了大括号,不推荐

使用Linq语法来检索

csharp
static void Main(string[] args)
{
    var names = new List<string> { "baidu", "qq", "malema", "tencent", "alibaba" };

    var hasAList = names.Where(x => x.Contains("a"));
    //string.Join是可以把集合合拼起来。
    Console.WriteLine(string.Join(",", hasAList));// baidu,malema,alibaba

    var query = from it in hasAList where it.Contains('a') select it; //跟sql有类似的语法
    Console.WriteLine(string.Join(",", hasAList));// baidu,malema,alibaba
}

例子2

csharp
static void Main(string[] args)
{
    var students = new List<Student>()
    {
        new Student(){ Id = 1, Name="Ma"},
        new Student(){ Id = 2, Name="Le"},
        new Student(){ Id = 3, Name="Ma2"},
        new Student(){ Id = 4, Name="Hello"},
        new Student(){ Id = 5, Name="linq"}
    };

    var list = students.Where(it => it.Id > 3).Select(x => x.Name);
    Console.WriteLine(string.Join(",", list));  //Hello,linq
}

在任意位置插入一个新的元素 Insert elements in list

下面的代码就将student插入到了第一个student Ma之前了

csharp
static void Main(string[] args)
{
    var students = new List<Student>()
    {
        new Student(){ Id = 1, Name="Ma"},
        new Student(){ Id = 2, Name="Le"},
        new Student(){ Id = 3, Name="Ma2"},
        new Student(){ Id = 4, Name="Hello"},
        new Student(){ Id = 5, Name="linq"}
    };

    var student = new Student() { Name = "m-a-l-e-m-a" };
    students.Insert(0, student);
}

从List当中移除一个元素 Remove elements from List

我们可以使用RemoveAt(index) Remove(T item) 如下我们通过两种方式来移除元素

csharp
static void Main(string[] args)
{
    var students = new List<Student>()
    {
        new Student(){ Id = 1, Name="Ma"},
        new Student(){ Id = 2, Name="Le"},
        new Student(){ Id = 3, Name="Ma2"},
        new Student(){ Id = 4, Name="Hello"},
        new Student(){ Id = 5, Name="linq"}
    };

    students.RemoveAt(0); //移除第一个元素
    Console.WriteLine(string.Join(",", students.Select(x => x.Name)));//Le,Ma2,Hello,linq
    students.Remove(students[0]);// 再次移除第一个元素
    Console.WriteLine(string.Join(",", students.Select(x => x.Name)));//Ma2,Hello,linq 

    //先找出要移除的元素
    var linqStudent = students.FirstOrDefault(it => it.Name == "linq");
    students.Remove(linqStudent);
    Console.WriteLine(string.Join(",", students.Select(x => x.Name)));//Ma2,Hello
}

传统方法 移除所有符合条件的

csharp
        static void Main(string[] args)
        {
            var students = new List<Student>()
            {
                new Student(){ Id = 1, Name="Ma"},
                new Student(){ Id = 2, Name="Le"},
                new Student(){ Id = 3, Name="Ma2"},
                new Student(){ Id = 4, Name="Hello"},
                new Student(){ Id = 5, Name="linq"}
            };

            foreach (var item in students.ToList())
            {
                // 为什么要在students后面加上.ToList因为不加的话会报错
                // System.InvalidOperationException:“Collection was modified; enumeration operation may not execute.”
                if (item.Name == "linq")
                {
                    students.Remove(item);
                }
            }
        }

可以用 students.RemoveAll(it => it.Name == "linq"); 代替上面的移除代码

判断元素是否存在

简单类型

csharp
var numbers = new List<int>() { 10, 20, 30, 40 };
numbers.Contains(10); // returns true
numbers.Contains(11); // returns false
numbers.Contains(20); // returns true

复杂类型

csharp
 static void Main(string[] args)
        {
            var students = new List<Student>()
            {
                new Student(){ Id = 1, Name="Ma"},
                new Student(){ Id = 2, Name="Le"},
                new Student(){ Id = 3, Name="Ma2"},
                new Student(){ Id = 4, Name="Hello"},
                new Student(){ Id = 5, Name="linq"}
            };

            var has = students.Any(x => x.Name == "linq"); //true
        }

构造函数

List<T>()初始化 List<T> 类的新实例,该实例为空并且具有默认初始容量。
List<T>(IEnumerable<T>)初始化 List<T> 类的新实例,该实例包含从指定集合复制的元素并且具有足够的容量来容纳所复制的元素。
List<T>(Int32)初始化 List<T> 类的新实例,该实例为空并且具有指定的初始容量。

属性

Capacity获取或设置该内部数据结构在不调整大小的情况下能够容纳的元素总数。
Count获取 List<T> 中包含的元素数。
Item[Int32]获取或设置指定索引处的元素。

方法

Add(T)将对象添加到 List<T> 的结尾处。
AddRange(IEnumerable<T>)将指定集合的元素添加到 List<T> 的末尾。
AsReadOnly()返回当前集合的只读 ReadOnlyCollection<T> 包装器。
BinarySearch(Int32, Int32, T, IComparer<T>)使用指定的比较器在已排序 List<T> 的某个元素范围中搜索元素,并返回该元素从零开始的索引。
BinarySearch(T)使用默认的比较器在整个已排序的 List<T> 中搜索元素,并返回该元素从零开始的索引。
BinarySearch(T, IComparer<T>)使用指定的比较器在整个已排序的 List<T> 中搜索元素,并返回该元素从零开始的索引。
Clear()从 List<T> 中移除所有元素。
Contains(T)确定某元素是否在 List<T> 中。
ConvertAll<TOutput>(Converter<T,TOutput>)将当前 List<T> 中的元素转换为另一种类型,并返回包含已转换元素的列表。
CopyTo(Int32, T[], Int32, Int32)从目标数组的指定索引处开始,将元素的范围从 List<T> 复制到兼容的一维数组。
CopyTo(T[])从目标数组的开头开始,将整个 List<T> 复制到兼容的一维数组。
CopyTo(T[], Int32)从目标数组的指定索引处开始,将整个 List<T> 复制到兼容的一维数组。
Equals(Object)确定指定对象是否等于当前对象。(继承自 Object)
Find(Predicate<T>)搜索与指定谓词所定义的条件相匹配的元素,并返回整个 List<T> 中的第一个匹配元素。
FindAll(Predicate<T>)检索与指定谓词定义的条件匹配的所有元素。
FindIndex(Int32, Int32, Predicate<T>)搜索与指定谓词所定义的条件相匹配的一个元素,并返回 List<T> 中从指定的索引开始、包含指定元素个数的元素范围内第一个匹配项的从零开始的索引。
FindIndex(Int32, Predicate<T>)搜索与指定谓词所定义的条件相匹配的元素,并返回 List<T> 中从指定索引到最后一个元素的元素范围内第一个匹配项的从零开始的索引。
FindIndex(Predicate<T>)搜索与指定谓词所定义的条件相匹配的元素,并返回整个 List<T> 中第一个匹配元素的从零开始的索引。
FindLast(Predicate<T>)搜索与指定谓词所定义的条件相匹配的元素,并返回整个 List<T> 中的最后一个匹配元素。
FindLastIndex(Int32, Int32, Predicate<T>)搜索与指定谓词所定义的条件相匹配的元素,并返回 List<T> 中包含指定元素个数、到指定索引结束的元素范围内最后一个匹配项的从零开始的索引。
FindLastIndex(Int32, Predicate<T>)搜索与由指定谓词定义的条件相匹配的元素,并返回 List<T> 中从第一个元素到指定索引的元素范围内最后一个匹配项的从零开始的索引。
FindLastIndex(Predicate<T>)搜索与指定谓词所定义的条件相匹配的元素,并返回整个 List<T> 中最后一个匹配元素的从零开始的索引。
ForEach(Action<T>)对 List<T> 的每个元素执行指定操作。
GetEnumerator()返回循环访问 List<T> 的枚举数。
GetHashCode()作为默认哈希函数。(继承自 Object)
GetType()获取当前实例的 Type。(继承自 Object)
IndexOf(T, Int32)搜索指定对象并返回 List<T> 中从指定索引到最后一个元素这部分元素中第一个匹配项的从零开始索引。
IndexOf(T, Int32, Int32)搜索指定对象并返回 List<T> 中从指定索引开始并包含指定元素数的这部分元素中第一个匹配项的从零开始索引。
Insert(Int32, T)将元素插入 List<T> 的指定索引处。
InsertRange(Int32, IEnumerable<T>)将集合中的元素插入 List<T> 的指定索引处。
LastIndexOf(T)搜索指定对象并返回整个 List<T> 中最后一个匹配项的从零开始索引。
LastIndexOf(T, Int32)搜索指定对象并返回 List<T> 中从第一个元素到指定索引这部分元素中最后一个匹配项的从零开始的索引。
LastIndexOf(T, Int32, Int32)搜索指定对象并返回 List<T> 中到指定索引为止包含指定元素数的这部分元素中最后一个匹配项的从零开始索引。
MemberwiseClone()创建当前 Object 的浅表副本。(继承自 Object)
RemoveAll(Predicate<T>)移除与指定的谓词所定义的条件相匹配的所有元素。
RemoveAt(Int32)移除 List<T> 的指定索引处的元素。
RemoveRange(Int32, Int32)从 List<T> 中移除一系列元素。
Reverse()将整个 List<T> 中元素的顺序反转。
Reverse(Int32, Int32)将指定范围中元素的顺序反转。
Sort()使用默认比较器对整个 List<T> 中的元素进行排序。
Sort(Comparison<T>)使用指定的 Comparison<T>,对整个 List<T> 中的元素进行排序。
Sort(IComparer<T>)使用指定的比较器对整个 List<T> 中的元素进行排序。
Sort(Int32, Int32, IComparer<T>)使用指定的比较器对 List<T> 中某个范围内的元素进行排序。
ToArray()将 List<T> 的元素复制到新数组中。
ToString()返回表示当前对象的字符串。(继承自 Object)
TrueForAll(Predicate<T>)确定 List<T> 中的每个元素是否都与指定谓词定义的条件匹配。

并发情况下对应的类型是 ConcurrentBag

简单就是美