C# 集合类 Array Arraylist List Hashtable Dictionary Stack Queue 泛型
1.数组是固定大小的,不能伸缩。虽然System.Array.Resize这个泛型方法可以重置数组大小,
但是该方法是重新创建新设置大小的数组,用的是旧数组的元素初始化。随后以前的数组就废弃!而集合却是可变长的
2.数组要声明元素的类型,集合类的元素类型却是object.
3.数组可读可写不能声明只读数组。集合类可以提供ReadOnly方法以只读方式使用集合。
4.数组要有整数下标才能访问特定的元素,然而很多时候这样的下标并不是很有用。集合也是数据列表却不使用下标访问。
很多时候集合有定制的下标类型,对于队列和栈根本就不支持下标访问!
总之一句话,数组初始时已经分配容量大小,即数组大小不可变。集合是可变的
泛型听起来很高深的一个词,但实际上它的作用很简单,就是提高c#程序的性能。
比如在计算机中经常用到一些数据结构,如队列,链表等,而其中的元素以前一般这么定义:object a=new object();
这样就带来一个严重的问题,用object来表示元素没有逻辑问题,但每次拆箱、封箱就占用了大量的计算机资源,导致程序性能低下,而这部分内容恰恰一般都是程序的核心部分,如果使用object,那么程序的表现就比较糟糕。
而使用泛型则很好的解决这个问题,本质就是在编译阶段就告诉编译器,数据结构中元素的种类,既然编译器知道了元素的种类,自然就避免了拆箱、封箱的操作,从而显著提高c#程序的性能。
比如List<string>就直接使用string对象作为List的元素,而避免使用object对象带来的封箱、拆箱操作,从而提高程序性能。
int[] intArray1; //初始化已声明的一维数组,并标明数据类型
intArray1 = new int[3]; // 实例时必须标明数组长度。
intArray1 = new int[3]{1,2,3};
intArray1 = new int[]{1,2,3};
string ss = "233,456";
string[] ass = ss.Split(new char[] { ',' }); //等价于string[] ass1 = ss.Split(',');
string str = string.Join(",", ass); // 结果str="233,456"
string str1 = string.Concat(ass);// 结果str1="233456"
数组通过下标的形式来找到指定的数据。
二 ArrayList类
ArrayList类对象被设计成为一个动态数组类型,其容量会随着需要而适当的扩充
方法
1:Add()向数组中添加一个元素,
2:Remove()删除数组中的一个元素
3:RemoveAt(int i)删除数组中索引值为i的元素
4:Reverse()反转数组的元素
5:Sort()以从小到大的顺序排列数组的元素
6:Clone()复制一个数组
2 using System.Collections.Generic;
3 using System.Text;
4 using System.Collections;
5 namespace ConsoleApplication1
6 {
7 class Program
8 {
9 static void Main(string[] args)
10 {
11 ArrayList al = new ArrayList();
12 al.Add(100);//单个添加
13 foreach (int number in new int[6]{ 9, 3, 7, 2, 4, 8 })
14 {
15 al.Add(number);//集体添加方法一//清清月儿 http://blog.csdn.net/21aspnet/
16 }
17 int[] number2 = new int[2]{ 11,12 };
18 al.AddRange(number2);//集体添加方法二
19 al.Remove(3);//移除值为3的
20 al.RemoveAt(3);//移除第3个
21 ArrayList al2 = new ArrayList(al.GetRange(1, 3));//新ArrayList只取旧ArrayList一部份
22
23
24 Console.WriteLine("遍历方法一:");
25 foreach (int i in al)//不要强制转换
26 {
27 Console.WriteLine(i);//遍历方法一
28 }
29
30 Console.WriteLine("遍历方法二:");
31 for (int i = 0; i != al2.Count; i++)//数组是length
32 {
33 int number = (int)al2[i];//一定要强制转换
34 Console.WriteLine(number);//遍历方法二
35
36 }
37 }
38 }
39 }
40
注意赋值的时候不做类型检查,但是在使用的时候如果强制转换成特定的类型将报错。故ArrayList 类是类型不安全的。
三 List
可通过索引访问的对象的强类型列表。提供用于对列表进行搜索、排序和操作的方法
在决定使用 List 还是使用 ArrayList 类(两者具有类似的功能)时,记住 List 类在大多数情况下执行得更好并且是类型安全的。如果对List 类的类型T 使用引用类型,则两个类的行为是完全相同的。但是,如果对类型 T 使用值类型,则需要考虑实现和装箱问题。如果对类型T 使用值类型,则编译器将特别针对该值类型生成 List 类的实现。这意味着不必对 List 对象的列表元素进行装箱就可以使用该元素,并且在创建大约 500 个列表元素之后,不对列表元素装箱所节省的内存将大于生成该类实现所使用的内存。
List<string> dinosaurs = new List<string>();//创建一个string的List集合
dinosaurs.Add("Tyrannosaurus");//向集合添加元素
Console.WriteLine("\nCapacity: {0}", dinosaurs.Capacity);
Console.WriteLine("Count: {0}", dinosaurs.Count);//输出集合中实际元素的数量
2 Console.WriteLine("\nCapacity: {0}", dinosaurs.Capacity);//输出默认容量的大小
3 dinosaurs.Add("Tyrannosaurus");//向集合添加元素
4 dinosaurs.Add("Amargasaurus");
5 dinosaurs.Add("test");
6 dinosaurs.Add("test1");
7 foreach (string dinosaur in dinosaurs)//打印集合中的元素
8 {
9 Console.WriteLine(dinosaur);
10 }
11
12 Console.WriteLine("\nCapacity: {0}", dinosaurs.Capacity);
13 Console.WriteLine("Count: {0}", dinosaurs.Count);//输出集合中实际元素的数量
14 Console.WriteLine("\nContains(\"Deinonychus\"): {0}", dinosaurs.Contains("Deinonychus"));//判断集合中是否包含某个元素
15 Console.WriteLine("\nInsert(2, \"Compsognathus\")");
16 Console.WriteLine("\nContains(\"Deinonychus\"): {0}", dinosaurs.Contains("Deinonychus"));//判断集合中是否包含某个元素 Console.WriteLine("\nInsert(2, \"Compsognathus\")");
17
18 dinosaurs.Insert(2, "Compsognathus");//将元素插入到集合的指定索引出,允许插入重复的元素
19 Console.WriteLine();
20 Console.WriteLine("\ndinosaurs[3]: {0}", dinosaurs[3]);//输出集合中索引为3的元素
21 Console.WriteLine("\nRemove(\"Compsognathus\")");
22 dinosaurs.Remove("Compsognathus");//移除集合中第一个匹配的元素
23 dinosaurs.TrimExcess();//减小容量以匹配计数,然后显示 Capacity 和 Count 属性。如果未用容量已经小于总容量的 10%,则列表容量不会进行调整。
24 Console.WriteLine("\nTrimExcess()");
25 Console.WriteLine("Capacity: {0}", dinosaurs.Capacity);
26 Console.WriteLine("Count: {0}", dinosaurs.Count);
27 dinosaurs.Clear();//移除列表中的所有项,然后显示 Capacity 和 Count 属性。
28 Console.WriteLine("\nClear()");
29 Console.WriteLine("Capacity: {0}", dinosaurs.Capacity);
30 Console.WriteLine("Count: {0}", dinosaurs.Count);
31 List<string> dinosaurs1 = new List<string>();//创建一个string的List集合
32 dinosaurs1.Add("Compsognathus");//向集合添加元素
33 dinosaurs1.Add("Amargasaurus");
34 dinosaurs1.Add("Oviraptor");
35 dinosaurs1.Add("Velociraptor");
36 dinosaurs1.Add("Deinonychus");
37 dinosaurs1.Add("Dilophosaurus");
38 dinosaurs1.Add("Gallimimus");
39 dinosaurs1.Add("Triceratops");
40 dinosaurs1.TrueForAll(EndsWithSaurus);//确定集合中的每个元素是否都与指定的谓词所定义的条件相匹配
41 dinosaurs1.Find(EndsWithSaurus);//搜索与指定谓词条件相匹配的第一个元素
42 dinosaurs1.FindLast(EndsWithSaurus);//搜索与指定谓词条件相匹配的最后一个元素
43 List<string> sublist = dinosaurs1.FindAll(EndsWithSaurus);//检索与指定谓词定义的条件匹配的所有元素
44 dinosaurs1.RemoveAll(EndsWithSaurus);//移除与指定谓词定义的条件匹配的所有元素
45 dinosaurs1.Exists(EndsWithSaurus);//该方法从头开始遍历该列表,依次将每个元素传递给 EndsWithSaurus 方法。如果 EndsWithSaurus 方法针对任何元素返回 true,搜索即停止
46 dinosaurs1.Sort();//对集合中的元素排序
47 dinosaurs1.Reverse();//将集合中的元素顺序反转
48 dinosaurs1.ForEach(Print);//对集合中的每个元素执行指定的方法(如Print方法)
49 // 搜索谓词方法,该方法接受一个字符串作为参数,并返回一个布尔值,指示输入的字符串是否以“saurus”结尾。
50 private static bool EndsWithSaurus(String s)
51 {
52 if ((s.Length > 5) && (s.Substring(s.Length - 6).ToLower() == "saurus"))
53 {
54 return true;
55 }
56 else
57 {
58 return false;
59 }
60 }
61 //定义打印集合的方法
62 private static void Print(string s)
63 {
64 Console.WriteLine(s);
65 }
1、 List<T> 类既使用相等比较器又使用排序比较器。
- 诸如 Contains、IndexOf、LastIndexOf 和 Remove 这样的方法对列表元素使用相等比较器。类型 T 的默认相等比较器按如下方式确定。如果类型 T 实现 IEquatable<T> 泛型接口,则相等比较器为该接口的 Equals(T) 方法;否则,默认相等比较器为 Object.Equals(Object)。
- 诸如 BinarySearch 和 Sort 这样的方法对列表元素使用排序比较器。类型 T 的默认比较器按如下方式确定。如果类型 T 实现 IComparable<T> 泛型接口,则默认比较器为该接口的 CompareTo(T) 方法;否则,如果类型 T 实现非泛型 IComparable 接口,则默认比较器为该接口的 CompareTo(Object) 方法。如果类型 T 没有实现其中任一个接口,则不存在默认比较器,并且必须显式提供比较器或比较委托。
2、 List<T> 不保证是排序的。在执行要求 List<T> 已排序的操作(例如 BinarySearch)之前,您必须对 List<T> 进行排序。
3、 使用整数索引可以访问此集合中的元素。此集合中的索引从零开始。
4、 List<T> 接受 null 作为引用类型的有效值并且允许有重复的元素。
5、 大多数情况下List<T>执行得更好并且是类型安全的,可以替换ArrayList,但是如果对类型 T 使用值类型,则编译器将特别针对该值类型生成 List<T> 类的实现。这意味着不必对 List<T> 对象的列表元素进行装箱就可以使用该元素,并且在创建大约 500 个列表元素之后,不对列表元素装箱所节省的内存将大于生成该类实现所使用的内存。如果创建小于500个元素,建议使用ArrayList.
四 Dictionary
表示键和值的集合。Dictionary遍历输出的顺序,就是加入的顺序,这点与Hashtable不同
Dictionary<string, string>是一个泛型 ,他本身有集合的功能有时候可以把它看成数组 ,他的结构是这样的:Dictionary<[key], [value]> ,他的特点是存入对象是需要与[key]值一一对应的存入该泛型
//实例化对象
Dictionary<int, string> dic = new Dictionary<int, string>();
//对象打点添加
dic.Add(1, "one");
dic.Add(2, "two");
dic.Add(3, "one");
//提取元素的方法
string a = dic[1];
string b = dic[2];
string c = dic[3];
//1、2、3是键,分别对应“one”“two”“one”
//上面代码中分别把值赋给了a,b,c
//注意,键相当于找到对应值的唯一标识,所以不能重复
//但是值可以重复
Dictionary<int, string> dic = new Dictionary<int, string>();
dic.Add(1, "HaHa");
dic.Add(5, "HoHo");
dic.Add(3, "HeHe");
dic.Add(2, "HiHi");
dic.Add(4, "HuHu");
var result = from pair in dic orderby pair.Key select pair;
foreach (KeyValuePair<int, string> pair in result)
{
Console.WriteLine("Key:{0}, Value:{1}", pair.Key, pair.Value);
}
五 SortedList类
与哈希表类似,区别在于SortedList中的Key数组排好序的
1、SortedList 的容量是 SortedList 可以保存的元素数。SortedList 的默认初始容量为 0。随着元素添加到 SortedList 中,在需要时可以通过重新分配自动增加容量。可通过调用 TrimToSize方法 或通过显式设置 Capacity 属性减少容量。
2、SortedList 中不允许重复键。
3、SortedList的索引顺序基于排序顺序。当添加元素时,元素将按正确的排序顺序插入 SortedList,同时索引会相应地进行调整。当移除元素时,索引也会相应地进行调整。因此,当在 SortedList 中添加或移除元素时,特定键/值对的索引可能会更改。
4.当不向集合中添加新元素,则调用TrimToSize方法可用于最小化集合的内存开销。
5、通过设置 SortedList 中不存在的键值(例如,myCollection["myNonexistentKey"] = myValue),还可以使用 Item 属性添加新元素。但是,如果指定的键已经存在于 SortedList 中,则设置 Item 属性将改写旧值。相比之下,Add 方法不修改现有元素。
键不能为 空引用(在 Visual Basic 中为 Nothing),但值可以。若要区分由于未找到指定键而返回的 空引用(在 Visual Basic 中为 Nothing) 和由于指定键的值为 空引用(在 Visual Basic 中为 Nothing) 而返回的 空引用(在 Visual Basic 中为 Nothing),请使用 Contains 方法或 ContainsKey 方法确定列表中是否存在该键。
六 Hashtable类
哈希表,名-值对。类似于字典(比数组更强大)。哈希表是经过优化的,访问下标的对象先散列过。如果以任意类型键值访问其中元素会快于其他集合。
GetHashCode()方法返回一个int型数据,使用这个键的值生成该int型数据。哈希表获取这个值最后返回一个索引,表示带有给定散列的数据项在字典中存储的位置。
1、HashTable定义
System.Collections. Hashtable类表示键/值对的集合,这些键/值对根据键的哈希代码进行组织, 每个元素都是一个存储在 DictionaryEntry 对象中的键/值对。键不能为 null,但值可以。
2.优点
1、通过Key快速查找。
2、Hashtable 是线程安全的。
Hashtable遍历方法
方法一
foreach (System.Collections.DictionaryEntry objDE in objHasTab)
{
Console.WriteLine(objDE.Key.ToString());
Console.WriteLine(objDE.Value.ToString());
}
方法二
System.Collections.IDictionaryEnumerator enumerator = objHashTablet.GetEnumerator();
while (enumerator.MoveNext())
{
Console.WriteLine(enumerator.Key); // Hashtable关健字
Console.WriteLine
}
Hashtable排序
//把ht的键对象全部复制到ArrayList中
ArrayList al = new ArrayList(ht.Keys);
/*ht.Keys返回ht中所有键对象构成的集合,把该集合传递给ArrayList构造方法则得到一个包
*所有键对象的动态数组
*/
al.Sort();//从小到大排列
//排序完成输出
for (int i = 0; i < al.Count;i++ )
{
object e=al[i];
object temp = (object)ht[e];//键作为索引器来获得对应的值对象
Console.WriteLine(temp.tostring());
}
七Stack类
栈,后进先出。push方法入栈,pop方法出栈。
1、Stack定义
System.Collections.Stack类表示对象的简单的后进先出非泛型集合。
2.优点
1、后进先出的集合。
2、Stack 能接受空引用作为有效值并且允许重复的元素
1、Stack 的容量是 Stack 可以保存的元素数。Stack 的默认初始容量为 10。向 Stack 添加元素时,将通过重新分配来根据需要自动增大容量。
2、容量是 Stack 可存储的元素数。Count 是 Stack 中实际存储的元素数,容量始终大于或等于 Count。如果在添加元素时 Count 超过容量,则通过在复制旧元素和添加新元素之前重新分配内部数组来自动增大容量
八Queue类
队列,先进先出。enqueue方法入队列,dequeue方法出队列。
1、Queue定义
System.Collections.Queue类表示对象的先进先出集合,存储在 Queue(队列) 中的对象在一端插入,从另一端移除。
2.优点
1、能对集合进行顺序处理(先进先出)。
2、能接受null值,并且允许重复的元素。
1、Queue 的容量是 Queue 可以保存的元素数。Queue 的默认初始容量为 32。向 Queue 添加元素时,将通过重新分配来根据需要自动增大容量。可通过调用 TrimToSize 来减少容量。等比因子是当需要更大容量时当前容量要乘以的数字。在构造 Queue 时确定增长因子。默认增长因子为 2.0。
2、Queue 能接受空引用作为有效值,并且允许重复的元素。
3、空引用可以作为值添加到 Queue。若要区分空值和 Queue 结尾,请检查 Count 属性或捕捉 Queue 为空时引发的 InvalidOperationException
-------------------------------------------------------------
//Dictionary
System.Collections.DictionaryEntry dic=new System.Collections.DictionaryEntry("key1","value1");
Dictionary<int, string> fruit = new Dictionary<int, string>();
//加入重复键会引发异常
fruit.Add(1, "苹果");
fruit.Add(2, "桔子");
fruit.Add(3, "香蕉");
fruit.Add(4, "菠萝");
//因为引入了泛型,所以键取出后不需要进行Object到int的转换,值的集合也一样
foreach (int i in fruit.Keys)
{
Console.WriteLine("键是:{0} 值是:{1}",i,fruit);
}
//删除指定键,值
fruit.Remove(1);
//判断是否包含指定键
if (fruit.ContainsKey(1))
{
Console.WriteLine("包含此键");
}
//清除集合中所有对象
fruit.Clear();
}
//ArrayList
System.Collections.ArrayList list=new System.Collections.ArrayList();
list.Add(1);
list.Add(2);
for(int i=0;i<list.Count;i++)
{
System.Console.WriteLine(list[i]);
}
//List
//声明一个List对象,只加入string参数
List<string> names = new List<string>();
names.Add("乔峰");
names.Add("欧阳峰");
names.Add("马蜂");
//遍历List
foreach (string name in names)
{
Console.WriteLine(name);
}
//向List中插入元素
names.Insert(2, "张三峰");
//移除指定元素
names.Remove("马蜂");
//HashTable
System.Collections.Hashtable table=new System.Collections.Hashtable();
table.Add("table1",1);
table.Add("table2",2);
System.Collections.IDictionaryEnumerator d=table.GetEnumerator();
while(d.MoveNext())
{
System.Console.WriteLine(d.Entry.Key);
}
//Queue
System.Collections.Queue queue=new System.Collections.Queue();
queue.Enqueue(1);
queue.Enqueue(2);
System.Console.WriteLine(queue.Peek());
while(queue.Count>0)
{
System.Console.WriteLine(queue.Dequeue());
}
//SortedList
System.Collections.SortedList list=new System.Collections.SortedList();
list.Add("key2",2);
list.Add("key1",1);
for(int i=0;i<list.Count;i++)
{
System.Console.WriteLine(list.GetKey(i));
}
//Stack
System.Collections.Stack stack=new System.Collections.Stack();
stack.Push(1);
stack.Push(2);
System.Console.WriteLine(stack.Peek());
while(stack.Count>0)
{
System.Console.WriteLine(stack.Pop());
}