list定义

当我们有很多类型一样的数据时,可以使用数组来进行存储并管理,但是这样的缺点是数组的大小是提前给定的、是固定的。 如果我们有许多类型一样但数量不定的数据,

我们可以使用集合类来进行管理——例如列表List。我们可以使用列表List很方便的添加数据,删除数据以及其他的一些数据操作。List类是ArrayList类的泛型等效类,该类使

用大小可按需动态增加的数组实现IList泛型接口。

泛型的好处:它为使用c#语言编写面向对象程序增加了极大的效力和灵活性。不会强行对值类型进行装箱和拆箱,或对引用类型进行向下强制类型转换,所以性能得到提高。
性能注意事项:在决定使用IList还是使用ArrayList类(两者具有类似的功能)时,记住IList类在大多数情况下执行得更好并且是类型安全的。如果对IList类的类型T 使用引用类
型,则两个类的行为是完全相同的。但是,如果对类型T 使用值类型,则需要考虑实现和装箱问题。

List的用法

1、List的基础、常用方法:

(1)、声明:
①、List mList = new List();
T为列表中元素类型,现在以string类型作为例子

1
List<string> mList = new List<string>();

②、List testList =new List (IEnumerable collection);

以一个集合作为参数创建List:

1
2
string[] temArr = { "Ha", "Hunter", "Tom", "Lily", "Jay", "Jim", "Kuku", "Locu" };
List<string> testList = new List<string>(temArr);

(2)、添加元素:

①、 添加一个元素

  语法: List. Add(T item)

1
2
List<string> mList = new List<string>();
mList.Add("John");

②、 添加一组元素

  语法: List. AddRange(IEnumerable collection)

1
2
3
List<string> mList = new List<string>();
string[] temArr = { "Ha","Hunter", "Tom", "Lily", "Jay", "Jim", "Kuku", "Locu" };
mList.AddRange(temArr);

③、在index位置添加一个元素

  语法: Insert(int index, T item);

1
2
List<string> mList = new List<string>();
mList.Insert(1, "Hei");

④、遍历List中元素

语法:

1
2
3
4
foreach (T element in mList)  //T的类型与mList声明时一样
{
Console.WriteLine(element);
}

例:

1
2
3
4
5
6
List<string> mList = new List<string>();
...//省略部分代码
foreach (string s in mList)
{
Console.WriteLine(s);
}

(3)、删除元素:

①、删除一个值

  语法:List. Remove(T item)

1
mList.Remove("Hunter");

②、 删除下标为index的元素

  语法:List. RemoveAt(int index);

1
mList.RemoveAt(0);

③、 从下标index开始,删除count个元素

  语法:List. RemoveRange(int index, int count);

1
mList.RemoveRange(3, 2);

(4)、判断某个元素是否在该List中:

语法:List. Contains(T item) 返回值为:true/false

1
2
3
4
5
6
7
8
9
if (mList.Contains("Hunter"))
{
Console.WriteLine("There is Hunter in the list");
}
else
{
mList.Add("Hunter");
Console.WriteLine("Add Hunter successfully.");
}

(5)、给List里面元素排序:

  语法: List. Sort () 默认是元素第一个字母按升序

1
mList.Sort();

(6)、给List里面元素顺序反转:

  语法: List. Reverse () 可以与List. Sort ()配合使用,达到想要的效果

1
mList. Reverse();

(7)、List清空:

  语法:List. Clear ()

1
mList.Clear();

(8)、获得List中元素数目:

  语法: List. Count () 返回int值

1
2
int count = mList.Count();
Console.WriteLine("The num of elements in the list: " +count);

2、List的进阶、强大方法:

本段举例用的List:

1
2
string[] temArr = { "Ha","Hunter", "Tom", "Lily", "Jay", "Jim", "Kuku", " "Locu" };
mList.AddRange(temArr);

(1)、List.FindAll方法:检索与指定谓词所定义的条件相匹配的所有元素

  语法:public List FindAll(Predicate match);

1
2
3
4
5
List<string> subList = mList.FindAll(ListFind); //委托给ListFind函数
foreach (string s in subList)
{
Console.WriteLine("element in subList: "+s);
}

这时subList存储的就是所有长度大于3的元素。

(2)、List.Find 方法:搜索与指定谓词所定义的条件相匹配的元素,并返回整个 List 中的第一个匹配元素。

  语法:public T Find(Predicate match);

Predicate是对方法的委托,如果传递给它的对象与委托中定义的条件匹配,则该方法返回 true。当前 List 的元素被逐个传递给Predicate委托,并在 List 中向前移动,从第一个元素开始,到最后一个元素结束。当找到匹配项时处理即停止。

Predicate 可以委托给一个函数或者一个拉姆达表达式:

委托给拉姆达表达式:

1
2
3
4
5
6
7
8
9
string listFind = mList.Find(name =>  //name是变量,代表的是mList中元素,自己设定
{
if (name.Length > 3)
{
return true;
}
return false;
});
Console.WriteLine(listFind); //输出是Hunter

委托给一个函数:

1
2
3
4
5
6
7
8
9
10
11
12
string listFind1 = mList.Find(ListFind);  //委托给ListFind函数
Console.WriteLine(listFind); //输出是Hunter

//ListFind函数
public bool ListFind(string name)
{
if (name.Length > 3)
{
return true;
}
return false;
}

这两种方法的结果是一样的。

(3)、List.FindLast 方法:搜索与指定谓词所定义的条件相匹配的元素,并返回整个 List 中的最后一个匹配元素。
  语法:public T FindLast(Predicate match);

用法与List.Find相同。

(4)、List.TrueForAll方法: 确定是否 List 中的每个元素都与指定的谓词所定义的条件相匹配。

  语法:public bool TrueForAll(Predicate match);

委托给拉姆达表达式:

1
2
3
4
5
6
7
8
9
10
11
12
bool flag = mList.TrueForAll(name =>
{
if (name.Length > 3)
{
    return true;
}
else
{
    return false;
}
});
Console.WriteLine("True for all: "+flag); //flag值为

委托给一个函数,这里用到上面的ListFind函数:

1
2
bool flag = mList.TrueForAll(ListFind);    //委托给ListFind函数
Console.WriteLine("True for all: "+flag); //flag值为false

这两种方法的结果是一样的。

(5)List.Take(n)方法: 获得前n行 返回值为IEnumetable,T的类型与List的类型一样

1
2
3
4
5
IEnumerable<string> takeList=  mList.Take(5);
foreach (string s in takeList)
{
Console.WriteLine("element in takeList: " + s);
}

这时takeList存放的元素就是mList中的前5个。

(6)、List.Where方法:检索与指定谓词所定义的条件相匹配的所有元素。跟List.FindAll方法类似。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
IEnumerable<string> whereList = mList.Where(name =>
{
if (name.Length > 3)
{
return true;
}
else
{
return false;
}
});

foreach (string s in subList)
{
Console.WriteLine("element in subLis

这时subList存储的就是所有长度大于3的元素。

(7)、List.RemoveAll方法:移除与指定的谓词所定义的条件相匹配的所有元素。

  语法: public int RemoveAll(Predicate match);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
mList.RemoveAll(name =>
{
if (name.Length > 3)
{
return true;
}
else
{
return false;
}
});

foreach (string s in mList)
{
Console.WriteLine("element in mList: " + s);
}

这时mList存储的就是移除长度大于3之后的元素。
补充请参考C#泛型类之LIST

C#泛型类之LIST

1、 定义

System.Collections.Generic.List类表示可通过索引访问的对象的强类型列表。提供用于对列表进行搜索、排序和操作的方法。T为类型参数,代表列表中元素的类型。该类实现了IList泛型接口,是ArrayList类的泛型等效类,其大小可按需动态增加。

2.构造函数

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

说明:默认向 List 添加元素时,将通过重新分配内部数组,根据需要自动增大容量。如果可以估计集合的大小,那么当指定初始容量后,将无需在向 List 中添加元素时执行大量的大小调整操作。这样可提高性能。

3. List方法

名称 说明
Add 将对象添加到 List 的结尾处。
AddRange 将指定集合的元素添加到 List 的末尾。
AsReadOnly 返回当前集合的只读 IList 包装。
BinarySearch(T) 使用默认的比较器在整个已排序的 List 中搜索元素,并返回该元素从零开始的索引。
BinarySearch(T, IComparer) 使用指定的比较器在整个已排序的 List 中搜索元素,并返回该元素从零开始的索引。
BinarySearch(Int32, Int32, T, IComparer) 使用指定的比较器在已排序 List 的某个元素范围中搜索元素,并返回该元素从零开始的索引。
Clear 从 List 中移除所有元素。
Contains 确定某元素是否在 List 中。
ConvertAll 将当前 List 中的元素转换为另一种类型,并返回包含转换后的元素的列表。
CopyTo(T[]) 将整个 List 复制到兼容的一维数组中,从目标数组的开头开始放置。
Exists 确定 List 是否包含与指定谓词所定义的条件相匹配的元素。
Find 搜索与指定谓词所定义的条件相匹配的元素,并返回整个 List 中的第一个匹配元素。
FindIndex(Predicate) 搜索与指定谓词所定义的条件相匹配的元素,并返回整个 List 中第一个匹配元素的从零开始的索引。
ForEach 对 List 的每个元素执行指定操作。
GetEnumerator 返回循环访问 List 的枚举器。
IndexOf(T) 搜索指定的对象,并返回整个 List 中第一个匹配项的从零开始的索引。
Insert 将元素插入 List 的指定索引处。
InsertRange 将集合中的某个元素插入 List 的指定索引处。
LastIndexOf(T) 搜索指定的对象,并返回整个 List 中最后一个匹配项的从零开始的索引。
Remove 从 List 中移除特定对象的第一个匹配项。
Reverse() 将整个 List 中元素的顺序反转。
Sort() 使用默认比较器对整个 List 中的元素进行排序。
TrimExcess 将容量设置为 List 中的实际元素数目(如果该数目小于某个阈值)。
TrueForAll 确定是否 List 中的每个元素都与指定的谓词所定义的条件相匹配。

说明:上述方法说明中有用到“谓词”,谓词就是Predicate 委托,它代表一组方法,该方法定义一组条件,并确定指定的参数对象是否符合这些条件,具体的参见示例程序。

4. List属性

名称 说明
Capacity 获取或设置该内部数据结构在不调整大小的情况下能够容纳的元素总数。
Count 获取 List 中实际包含的元素数。

说明:Capacity 是 List 在需要调整大小之前可以存储的元素数,Count 则是 List 中实际存储的元素数。

5.示例程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
 class Program
{
static void Main(string[] args)
{
#region List<T>类常用的方法
List<string> dinosaurs = new List<string>();//创建一个string的List集合

Console.WriteLine("\nCapacity: {0}", dinosaurs.Capacity);//输出默认容量的大小

dinosaurs.Add("Tyrannosaurus");//向集合添加元素
dinosaurs.Add("Amargasaurus");
dinosaurs.Add("Mamenchisaurus");
dinosaurs.Add("Deinonychus");
dinosaurs.Add("Compsognathus");

Console.WriteLine();
foreach (string dinosaur in dinosaurs)//打印集合中的元素
{
Console.WriteLine(dinosaur);
}

Console.WriteLine("\nCapacity: {0}", dinosaurs.Capacity);
Console.WriteLine("Count: {0}", dinosaurs.Count);//输出集合中实际元素的数量

Console.WriteLine("\nContains(\"Deinonychus\"): {0}",
dinosaurs.Contains("Deinonychus"));//判断集合中是否包含某个元素

Console.WriteLine("\nInsert(2, \"Compsognathus\")");
dinosaurs.Insert(2, "Compsognathus");//将元素插入到集合的指定索引出,允许插入重复的元素

Console.WriteLine();
foreach (string dinosaur in dinosaurs)//打印集合中的元素
{
Console.WriteLine(dinosaur);
}
Console.WriteLine("\ndinosaurs[3]: {0}", dinosaurs[3]);//输出集合中索引为3的元素

Console.WriteLine("\nRemove(\"Compsognathus\")");
dinosaurs.Remove("Compsognathus");//移除集合中第一个匹配的元素

Console.WriteLine();
foreach (string dinosaur in dinosaurs)//打印集合中的元素
{
Console.WriteLine(dinosaur);
}
dinosaurs.TrimExcess();//减小容量以匹配计数,然后显示 Capacity 和 Count 属性。如果未用容量已经小于总容量的 10%,则列表容量不会进行调整。
Console.WriteLine("\nTrimExcess()");
Console.WriteLine("Capacity: {0}", dinosaurs.Capacity);
Console.WriteLine("Count: {0}", dinosaurs.Count);

dinosaurs.Clear();//移除列表中的所有项,然后显示 Capacity 和 Count 属性。
Console.WriteLine("\nClear()");
Console.WriteLine("Capacity: {0}", dinosaurs.Capacity);
Console.WriteLine("Count: {0}", dinosaurs.Count);

#endregion

#region List<T>类的新增方法

List<string> dinosaurs1 = new List<string>();//创建一个string的List集合

dinosaurs1.Add("Compsognathus");//向集合添加元素
dinosaurs1.Add("Amargasaurus");
dinosaurs1.Add("Oviraptor");
dinosaurs1.Add("Velociraptor");
dinosaurs1.Add("Deinonychus");
dinosaurs1.Add("Dilophosaurus");
dinosaurs1.Add("Gallimimus");
dinosaurs1.Add("Triceratops");

Console.WriteLine();
foreach (string dinosaur in dinosaurs1)
{
Console.WriteLine(dinosaur);
}

Console.WriteLine("\nTrueForAll(EndsWithSaurus): {0}",
dinosaurs1.TrueForAll(EndsWithSaurus));//确定集合中的每个元素是否都与指定的谓词所定义的条件相匹配

Console.WriteLine("\nFind(EndsWithSaurus): {0}",
dinosaurs1.Find(EndsWithSaurus));//搜索与指定谓词条件相匹配的第一个元素

Console.WriteLine("\nFindLast(EndsWithSaurus): {0}",
dinosaurs1.FindLast(EndsWithSaurus));//搜索与指定谓词条件相匹配的最后一个元素

Console.WriteLine("\nFindAll(EndsWithSaurus):");
List<string> sublist = dinosaurs1.FindAll(EndsWithSaurus);//检索与指定谓词定义的条件匹配的所有元素

foreach (string dinosaur in sublist)//打印集合
{
Console.WriteLine(dinosaur);
}

Console.WriteLine(
"\n{0} elements removed by RemoveAll(EndsWithSaurus).",
dinosaurs1.RemoveAll(EndsWithSaurus));//移除与指定谓词定义的条件匹配的所有元素

Console.WriteLine("\nList now contains:");
foreach (string dinosaur in dinosaurs1)//打印集合
{
Console.WriteLine(dinosaur);
}

Console.WriteLine("\nExists(EndsWithSaurus): {0}",
dinosaurs1.Exists(EndsWithSaurus));//该方法从头开始遍历该列表,依次将每个元素传递给 EndsWithSaurus 方法。如果 EndsWithSaurus 方法针对任何元素返回 true,搜索即停止
dinosaurs1.Sort();//对集合中的元素排序
dinosaurs1.Reverse();//将集合中的元素顺序反转
dinosaurs1.ForEach(Print);//对集合中的每个元素执行指定的方法(如Print方法)
Console.Read();
#endregion
}

// 搜索谓词方法,该方法接受一个字符串作为参数,并返回一个布尔值,指示输入的字符串是否以“saurus”结尾。
private static bool EndsWithSaurus(String s)
{
if ((s.Length > 5) &&
(s.Substring(s.Length - 6).ToLower() == "saurus"))
{
return true;
}
else
{
return false;
}
}

//定义打印集合的方法
private static void Print(string s)
{
Console.WriteLine(s);
}

}

6.备注

1、 List 类既使用相等比较器又使用排序比较器。

  • 诸如 Contains、IndexOf、LastIndexOf 和 Remove 这样的方法对列表元素使用相等比较器。类型 T 的默认相等比较器按如下方式确定。如果类型 T 实现 IEquatable 泛型接口,则相等比较器为该接口的 Equals(T) 方法;否则,默认相等比较器为 Object.Equals(Object)。
  • 诸如 BinarySearch 和 Sort 这样的方法对列表元素使用排序比较器。类型 T 的默认比较器按如下方式确定。如果类型 T 实现 IComparable 泛型接口,则默认比较器为该接口的 CompareTo(T) 方法;否则,如果类型 T 实现非泛型 IComparable 接口,则默认比较器为该接口的 CompareTo(Object) 方法。如果类型 T 没有实现其中任一个接口,则不存在默认比较器,并且必须显式提供比较器或比较委托。

2、 List 不保证是排序的。在执行要求 List 已排序的操作(例如 BinarySearch)之前,您必须对 List 进行排序。

3、 List 不保证是排序的。在执行要求 List 已排序的操作(例如 BinarySearch)之前,您必须对 List 进行排序。

4、 使用整数索引可以访问此集合中的元素。此集合中的索引从零开始。

5、 List 接受 null 作为引用类型的有效值并且允许有重复的元素。

6、 大多数情况下List执行得更好并且是类型安全的,可以替换ArrayList,但是如果对类型 T 使用值类型,则编译器将特别针对该值类型生成 List 类的实现。这意味着不必对 List 对象的列表元素进行装箱就可以使用该元素,并且在创建大约 500 个列表元素之后,不对列表元素装箱所节省的内存将大于生成该类实现所使用的内存。如果创建小于500个元素,建议使用ArrayList.

用CopyTo方法将List集合元素拷贝到数组Array

在C#的List集合操作中,有时候需要将List元素对象拷贝存放到对应的数组Array中,此时就可以使用到List集合的CopyTo方法来实现,CopyTo方法是List集合的扩展方法,共有3个重载方法签名,分别为void CopyTo(T[] array)、void CopyTo(T[] array, int arrayIndex)、void CopyTo(int index, T[] array, int arrayIndex, int count)等三种形式,此文重点介绍CopyTo的第一种方法签名形式void CopyTo(T[] array)。

首先定义个用于测试的类TestModel,具体的类定义如下:

1
2
3
4
5
6
public class TestModel
{
public int Index { set; get; }

public string Name { set; get; }
}

然后定义一个List集合,并往里面写入3条TestModel数据,具体实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
List<TestModel> testList = new List<ConsoleApplication1.TestModel>();
testList.Add(new TestModel()
{
Index=1,
Name="Index1"
});
testList.Add(new TestModel()
{
Index = 2,
Name = "Index2"
});
testList.Add(new TestModel()
{
Index = 3,
Name = "Index3"
});

我们需要达到的目的是,将testList集合的元素对象拷贝到数组Array中,此时可使用下列语句实现:

1
2
TestModel[] copyArray = new TestModel[testList.Count];
testList.CopyTo(copyArray);

注意:上述程序语句中的CopyTo方法为浅层次拷贝,当修改copyArray数组的时候,也会联动修改List集合对象testList。例如赋值copyArray[0].Index = 10后,List集合对象testList的第一个元素testList[0]对象的Index属性也被修改为10。

List 二维数组的使用(最重要的!踩了坑才记录这篇文章)

C#泛型列表List实现二维数组的功能(令附C#泛型列表List基本用法总结)

是通过这篇文章才解决画图时传入多维数组数组问题

在决定使用 List 还是使用 ArrayList 类(两者具有类似的功能)时,记住 List 类在大多数情况下执行得更好并且是类型安全的。 如果对 List 类的类型 T 使用引用类型,则两个类的行为是完全相同的。 但是,如果对类型 T 使用值类型,则需要考虑实现和装箱问题。想二维数组和一维数组那样能用好多方法,在这里可以实现:那就是利用泛型List

举个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
view plaincopy to clipboardprint?
List<List<int>> array1 = new List<List<int>>();
List<int> array2 = new List<int>();

array2.Add(2);
array2.Add(3);
array2.Add(6);
array2.Add(6);
array2.Add(6);
List<int> array3 = new List<int>();
array3.Add(1);
array3.Add(4);
array3.Add(5);
array3.Add(12);
array3.Add(32);
array3.Add(42);
array1.Add(array2);
array1.Add(array3);
List<string> array4 = array1[0];
List<string> array5 = array1[1];

-—————————————————————–

原理是:把列表合并再拆开,把数组中的每一行看做是一个列表的数据。

代码中定义两个列表的类型array1,利用List的方法赋值,之后拆开,把值传到两个列表中。这样就实现了二维数组的赋值取值。这是二维数组,多维数组举一反三。例子只是为了说明用法 毫无代码价值。

C#泛型列表List基本用法总结:(饮水思源:http://space.itpub.net/14466241/viewspace-624132)

示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
namespace SampleListT
{
class Program
{
static void Main(string[] args)
{
//using System.Collections.Generic; 命名空间中的List<T>
//using System.Collections; 命名空间中的ArrayList
//都实现了列表集合,一个是泛形集合,一个是非泛型的
//下面我们将Person对象加到集合中

​ Person p1 = new Person( "aladdin" , 20 );
​ Person p2 = new Person("zhao", 10);
​ Person p3 = new Person("jacky", 40);

//如果不制定list的容器大小,默认是0,只要有元素加入是,会自动扩展到4,如果第5个元素加入时,就变成了8,第9个加入,就成16
//可以看出,总是成倍的增长,扩展时要重新开辟内存,这样会影响效率,如果事先知道元素个数,或者可能个数,最好给个尽量大的权衡值
//我们加入3个元素,设容器大小为4.注:设为4不是指只能放4个元素,如果超出,一样也会成倍扩展,这样做只是为了尽量扩展带来的开销
​ List<Person> list = new List<Person>(4);
​ list.Add(p1);
​ list.Add(p2);
​ list.Add(p3);

//本方法是清除多于的没有用的内存空间,例:如果开辟大小为100,而我们只用了4个,其余的放着,是不是很浪费 
//本方法调用时会检查元素个数是不是占到了容器大小的90%以上,如果是,则不进行回收.
​ list.TrimExcess();

//ArrayList方法与List<>用法一样,不同的是,它是对象集合,参数是Object这样会有装箱拆箱的可能,尽量用List<>
//本处不再做演示

// 1 初始化集合器
// C#3.0开始,提供了初始化功能,但是并没有反应到IL代码中,在IL中,一样也是把个转化成ADD方法来调用
​ List<int> l2 = new List<int>() { 1 ,2 ,3 ,4 ,5 };

// 2 添加元素 AddRange() 本方法可以一次性添加一批对象
​ List<Person> lists = new List<Person>(10);
//参数是一个必须可能跌代的对象,也可是数组
​ list.AddRange( new Person[] { new Person( "aladdin" ,20) , new Person("zhao",6)});

//构造传入批量参数 ,与AddRange效果一样
​ List<Person> mylist = new List<Person>(new Person[] { new Person( "aladdin" ,20) , new Person("zhao",6)});

// 3 插入元素
// 使用Insert()方法,可以在指定位置插入元素
// 例 我们在1位置插入 则最后变成了 aladdin jacky zhao..插入意思就是,这个位我占了,以前占这位的和他之后的,通通往后移一位
​ mylist.Insert( 1 , new Person( "jacky" , 88 ));

foreach (Person p in mylist)
​ {
​ Console.WriteLine(p.name);
​ }

// 4 访问元素
// ArrayList 与 List<T>都是提供了索引器来访问的
​ Console.WriteLine( "----------------访问元素------------------------");

for (int i = 0; i < mylist.Count; i++)
​ {
​ Console.WriteLine(mylist[i].name);
​ }
//还可以使用foreach跌代器来实现,些处不再举例

//使用Foreach方法
//public delegate void Action<T>(T obj);例用委托做为参数
//些处我们用呀妈Day表达式实现
​ Console.WriteLine( "-----------------用ForEach方法输出------------------------");

​ mylist.ForEach( param => Console.WriteLine(param.name) ) ;

// 5删除元素
//删除元素可以使用RemoveAt()直接传入索引器值
//将第一个元素直接删除
​ mylist.RemoveAt(0);
//也可以将要删除的元素传给Remove方法

​ List<Person> lists2 = new List<Person>(10);

​ Person per1 = new Person( "aladdin" , 100 );
​ Person per2 = new Person("zhao", 100);
​ Person per3 = new Person("jacky", 100);

​ lists2.Add(per1);
​ lists2.Add(per2);
​ lists2.Add(per3);

​ lists2.Remove(per3);

​ Console.WriteLine( "-------删除后的元素---------");

foreach (Person per in lists2)
​ {
​ Console.WriteLine(per.name);
​ }
//从结果可以看出 名称为Jacky的元素被删除了
//下面说一下Remove方法的删除过程
// 用IndexOf方法确定出对象的索引,然后按索引删除
// 在IndexOf方法内,首先检查元素是不是实现了IEquatable接口,如果是,就调用这个接口中的Equals方法
// 如果没有实现,则调用Object中的Equals方法比较元素(也就是址址比较)
// 以上我们删除per3,很显明显一个地址,所以被删除了

// 下面我们改装了Person ,实现了IEquatable<Person>,在比较方法中,始终返回false , 则per3会比较失败,不会被删除
// 结果3个都在
// 如果要删除对象,最好使用索引直接删除,因为Remove方法经历了一系列过程后,最后才按索引删除!

// RemoveRange()删除一个范围
// 第一个参数 开始位置 第二个 个数
//lists2.RemoveRange( 1 , 2 );
//Console.WriteLine( "批量删除后----------------");

//foreach (Person per in lists2)
//{
// Console.WriteLine(per.name);
//}

// 6 搜索
// 搜索有很多种方式,可以使用IndexOf LastIndexOf FindIndex FindLasIndex Find FindLas ,如果只是查看元素存不,可以使用Exists()方法
// IndexOf() 方法 需要将一个对象做参数, 如果打到,就返回本元素在集合中的索引,如果找不到就返回-1,IndexOf还可以使用IEquatable接口来比较元素

​ List<Person> ls3 = new List<Person>(10);

​ Person person1 = new Person("aladdin", 100);
​ Person person2 = new Person("zhao", 100);
​ Person person3 = new Person("jacky", 100);

​ ls3.Add(person1);
​ ls3.Add(person2);
​ ls3.Add(person3);

// 为了使用默认的地址比较,我们把Person的接口暂时去掉
int index = ls3.IndexOf(person3);
​ Console.WriteLine( "per3 的索引:" + index); //2
// 还可以指定搜索范围 从第3个开始,范围长度是1
int index2 = ls3.IndexOf(person3,2,1);
​ Console.WriteLine(index2);
//IEquatable比较方法前面已经写过,不再举例

// FindIndex()方法是用来搜索带有一定特性的元素
// 例用委托做参数 public delegate bool Predicate<T>(T obj);

int index3 = ls3.FindIndex(param => param.name.Equals("jacky"));
​ Console.WriteLine( index3 );// 2
// FindLastIndex是从后面查第一个出现的元素,因为我们这里没有重复元素,所以体现不出他只查找一个,就停下来的效果
int index4 = ls3.FindLastIndex(p => p.name.Equals("aladdin"));
​ Console.WriteLine(index4);
// Find方法与FindIndex方法用法一样,不同的是,它返回的是元素本身
​ Person ppp = ls3.Find( p => p.name.Equals("jacky")) ;
​ Console.WriteLine(ppp);

// 如果要查找所有的匹配元素,而不是找到第一个就停下来,就使用FindAll方法
// 我们查找所有年纪等于100的对象,3个都符合
​ List<Person> newList = ls3.FindAll(p => p.age == 100);

​ Console.WriteLine( "----------查找所有---------");

foreach (Person p in newList)
​ {
​ Console.WriteLine(p.name);
​ }

// 7 排序
// List可以例用Sort方法排序,实现算法是快速排序
// 本方法有好几个重载
//public void Sort(); //只对元素实现了IComparable才能使用这个方法 ,如果实现了则,可以直接调用一次sort之后,就排好序了
//public void Sort(Comparison<T> comparison); //我们的Person并没有实现那个接口,所以要用泛型委托当参数的方法
//public void Sort(IComparer<T> comparer); //泛型接口当参数 public delegate int Comparison<T>(T x, T y);
//public void Sort(int index, int count, IComparer<T> comparer); //可以指定范围

​ List<Person> ls4 = new List<Person>(10);

​ Person person4 = new Person("aladdin", 100);
​ Person person5 = new Person("zhao", 33);
​ Person person6 = new Person("jacky", 44);

​ ls4.Add(person4);
​ ls4.Add(person5);
​ ls4.Add(person6);

​ ls4.Sort(MyComparFunc);
​ Console.WriteLine( "-------------排序后的-------------");

foreach (Person p in ls4)
​ {
​ Console.WriteLine(p.name+ p.age );
​ }

​ Console.WriteLine( "--------颠倒循序------------------");
​ ls4.Reverse();

foreach (Person p in ls4)
​ {
​ Console.WriteLine(p.name+ p.age);
​ }

// 8 类型转换

//可以将集合中的元素转换成任意类型的元素,比如,我们要将集合中的Person转换成为Racer对象Racer只包含名字,没有年纪
// public List<TOutput> ConvertAll<TOutput>(Converter<T, TOutput> converter);
// public delegate TOutput Converter<TInput, TOutput>(TInput input); 委托参数
List<Racer> ls5 = ls4.ConvertAll<Racer>((input) => new Racer(input.name)) ;

​ Console.WriteLine( "-----------转换后的玩意--------");
foreach (Racer r in ls5)
​ {
​ Console.WriteLine(r.name);
​ }

// 9 只读集合
// 在创建完集合以后,肯定是可读写的,如果不是,他就不能再添加新元素了,但是,如果是认为填充完毕,不要再做修改.
// 可以使用只读集合,使用AsReadOnly方法() 返回ReadOnlyCollection<T>类型,它与List<>操作是一样的,但是一但有修改集合的操作,就会刨出异常
// 他屏蔽了通常的ADD等方法

​ ReadOnlyCollection<Racer> persss = ls5.AsReadOnly();

​ Console.WriteLine("输出只读集合");

foreach (Racer r in persss)
​ {
​ Console.WriteLine(r.name);
​ }

​ Console.ReadLine();

}

//为了比较写的委托实现方法
public static int MyComparFunc(Person p1, Person p2)
{
if (p1.age == p2.age)
{
return 0;
}
else if (p1.age > p2.age)
{
return 1;
}
else
{
return -1;
}
}
}

//two helper classes
class Person//:IEquatable<Person>
{
public string name;
public int age;

public Person( string name , int age )
{
this.name= name;
this.age = age;
}

////始终给一个False值
//public bool Equals(Person other)
//{
// return false;
//}

}

class Racer
{
public string name;

public Racer(string name)
{
this.name= name;
}
}

}

用List创建二维数组(未测试过,应当为正常)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
List<List<int>> dList = new List<List<int>>();

List<int> list = new List<int>(new int[]{10,1,13,16,17});

List<int> list2 = new List<int>(new int[]{21,2,23,26,27});

dList.Add(list);
dList.Add(list);

for(int i=0; i < dList.Count; i++)
{
for(int j=0; j < dList[i].Count; j++)
{
Console.Write(dList[i][j]+",");
}
Console.WriteLine("第{0}行数据",i);
}

最近在解决一个地图图层操作的问题,图层操作的原理大致是这样的:
每层图片划分为同样大小的网格,划分后可以看成一个二维数组,每一个网格代表数组中的一个元素,将其转化 为一 维数组(后面还会增加一维,由于对超过二维的数组有一种天然的的恐惧感,这里就把其转化为一维的了);
将每一层看做一维数组中的一个元素,这样对图层的操作就变成一个对二维数组的操作;
预设的目标是能够实现动态的增加图层,增加的图层放在最上层;
相邻两个图层之间能够交换顺序,即数组list[0]和数组list[1]能够交换位置;
能够删除某一指定的层;
就如上上面提到的一样,我想到的解决办法就是使用二维数组,但我需要的图层数目是动态的增加和减少的,而且某一层的顺序位置是可以变化的,这就涉及到数组的添加,删除,顺序变化,这些是普通的二维数组是实现不了的,于是就想到是用List,然后就在网上查了一些资料和MSDN文档,写了下面的测试代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int[] a = new int[5];
int[] b = new int[5];
int[] c = new int[5];
int[] d = new int[5];
int[] e = new int[5];
int[] f = new int[5]; //创建一维数组
List<int[]> list = new List<int[]>();
list.Add(a);
list.Add(b);
list.Add(c);

list.Add(d); //添加图层
list[0][3] = 20;
list[1][2] = 2; //这里和普通二维数组的使用[,] 不一样
list[2][3] = 40;

list.Reverse(1,2); //图层交换

相关链接(侵删)

  1. C# 之list
  2. C#泛型类之LIST
  3. C#中List用法介绍详解(这个说的很详细)
  4. C#中使用CopyTo方法将List集合元素拷贝到数组Array中
  5. C#泛型列表List实现二维数组的功能(令附C#泛型列表List基本用法总结)
  6. 关于 List[][] 大家见过这样的用法么?
  7. C# 创建二维List的简单例子

=================我是分割线=================

欢迎到公众号来唠嗑: