C#集合详解
来源:互联网 发布:淘宝店铺地址怎么改ip 编辑:程序博客网 时间:2024/05/21 07:11
以下是对最长用的集合进行简单的总结
List<T>
可以像数组一样按索引访问列表,但提供了其他方法来搜索和排序 Queue<T>
先入先出数据结构,提供了方法将数据项添加到队列的一段,从另一端删除项,以及只检查不删除 Stack<T>
先入后出数据结构,提供了方法将数据压入栈顶,从栈顶出栈,以及只检查栈顶的项而不删除 LinkedList<T>
双向有序列表,为任何一端的插入和删除进行了优化,这种集合既可作为队列,也可作为栈,还支持列表那样的随机访问 HashSet<T>
无序值列表,为快速数据获取而优化,提供了面向集合的方法来判断它容纳的项是不是另一个HashSet<T>
对象中的项的子集,以及计算不同HashSet<T>
对象的交集和并集 Dictionary<TKey,TValue>
字典集合允许根据键而不是索引来获取值 SortedList<TKey,TValue>
键/值对的有序列表,键必须实现Icomparable<T>
接口先来了解下集合的基本信息:
1、BCL中集合类型分为泛型集合与非泛型集合。
2、非泛型集合的类和接口位于System.Collections命名空间。
3、泛型集合的类和接口位于System.Collections.Generic命名空间。
ICollection接口是System.Collections命名空间中非泛型集合类的基接口,它继承自IEnumerable接口,从IEnumerable接口继承意味着实现该接口的实现类需要实现一个枚举器方法:GetEnumerator,该方法返回IEnumerator类型的数据。IDictionary和IList接口继承自ICollection作为更为专用的接口,其中IDictionary接口是键/值对接口,它的实现如HashTable类;而IList是值的集合,其成员可通过索引访问,如ArrayList类,次类集合与数组相比,可以认为是可变的集合,优点有,长度自动增长等。IEnumerable和IEnumerable是所有集合或集合接口的基接口,所有集合接口或集合都继承、实现了它。其中IEnumerable是最底层的接口。在非泛型集合里存放的都是System.Object类型。
一、下面列出非泛型和泛型集合的接口
ICollection
ICollection<T>
定义所有集合的大小(Count),枚举器(foreach)和同步(copyto)方法,继承自IEnumerable
IList
IList<T>
表示可按照索引单独访问的一组对象(像数组一样) IDictionary
IDictionary<T>
表示键/值对的集合 IComparer
IComparer<T>
定义类型为比较两个对象而实现的方法 IEqualityComparer
IEqualityComparer<T>
定义方法以支持对象的相等比较 IEnumerable
IEnumerable<T>
公开枚举器。实现了该接口意味着允许foreach语句循环访问集合中的元素 IEnumerator
IEnumerator<T>
支持在泛型集合上进行简单迭代下面来详细介绍各种集合接口和集合。个人认为应该从根底说起。
先抱着MSDN来说IEnumerable,扩展方法就不说了,扩展方法跳过,留到学Linq的时候再说。
1.IEnumerable接口就一个方法,没有属性
2、IEnumerable<T>
接口也一样,也是就一个方法,没有属性。
3、ICollection接口
4、ICollection<T>
ICollection<T>
中包含的元素数。 IsReadOnly 获取一个值,该值指示 ICollection<T>
是否为只读。 属性 Add 将某项添加到 ICollection<T>
中。 Clear 从 ICollection<T>
中移除所有项。 Contains 确定 ICollection<T>
是否包含特定值。 CopyTo 从特定的 Array 索引开始,将 ICollection<T>
的元素复制到一个 Array 中。 GetEnumerator 已重载。 Remove 从 ICollection<T>
中移除特定对象的第一个匹配项。 这个ICollect<T>
,才开始有点集合的影子了,可以Add、Clear了,怪不得它作为泛型集合接口的基类。
5、IList
IList继承了ICollection和IEnumerable
6、IList<T>
IList<T>
继承了ICollection<T>
,IEnumerable<T>
,IEnumerable
7、IDictionary<TKey,TValue>
接口 IDictionary<TKey,TValue>
是最底层出现的键/值对集合了,相当于值集合中的ICollection
8、IDictionary
9、ISet<T>
Set<T>
同样是继承自ICollection<T>
,IEnumerable<T>
,IEnumerable
先说IComparer接口,这个接口就一个方法,用于如何比较两个对象
public class StringLengthComparer : IComparer<string> { public int Compare(string s1, string s2) { if (s1.Length > s2.Length) { return (1); } else if (s1.Length < s2.Length) { return (2); } else { return (0); } } }
说完了集合接口,现在开始说集合。
1、ArrayList
ArrayList实现了IList、ICollection、IEnumerable接口。
ArrayList与Array的名字很相似,现在来比较一下两者的异同。
相同点:
(1)、两者都实现了IList、ICollection、IEnumerable接口。
(2)、两者都可以使用整数索引访问集合中的元素,包括读取和赋值,且集合中的索引都从0开始。
不同点:
(1)、ArrayList是集合,而Array是数组。
(2)、ArrayList是具体类,Array是抽象类。
(3)、数组必须在实例化时指定元素的数量,该数量一旦确定就不可以更改了,而ArrayList扩展了这一点,当实例化一个ArrayList实例时可以不指定集合元素数(有默认初始容量),当然你也可以指定初始容量。
(4)、获取数组的元素数时使用Length属性,而获取ArrayList集合的元素数时使用Count属性。
(5)、数组可以有多维,而ArrayList只能是一维。
来看ArrayList具体提供的功能
集合-ArrayList的用法
static void Main(string[] args) { ArrayList arrayList = new ArrayList(); arrayList.Add(1); //Add方法,将一个元素添加到ArrayList中 arrayList.Add("你好"); arrayList.Add(3.265); IList iList = arrayList; ICollection iCollection = iList; IEnumerable iEnumerable = iCollection; //体现了ArrayList的继承关系 foreach (object obj in iEnumerable) { Console.WriteLine(obj.ToString()); } bool b = arrayList.Contains("你好"); //确定ArrayList中是否包含某元素 Console.WriteLine(b); //输出 True object[] objArr = new object[arrayList.Count + 1]; objArr[0] = "我是用来占位的"; arrayList.CopyTo(objArr, 1); //便宜一位,也就是接受数组从1开始,默认是0 foreach (object obj in objArr) { Console.Write(obj.ToString() + "-"); //输出 我是用来占位的-1-你好-3.265- } Console.WriteLine(); ArrayList AL = ArrayList.FixedSize(arrayList); //静态方法 返回一个固定大小的ArrayList对象,数量不许改变。也就是说不能添加和删除。 Console.WriteLine(AL.IsFixedSize); //输出True //AL.Add(111); 此处报异常,"集合的大小是固定的" ArrayList ALReadOnly = ArrayList.ReadOnly(arrayList); Console.WriteLine(ALReadOnly.IsReadOnly); //输出True ArrayList AL1 = arrayList.GetRange(1, 2); //按照索引顺序截取出子集 foreach (object obj in AL1) { Console.Write(obj.ToString()); //输出 你好3.265 可以截取出的新ArrayList只包含1,2位 } Console.WriteLine(); int indexLocation = arrayList.IndexOf(1); //从左边开始检索,返回第一个匹配到的元素的顺序 Console.WriteLine(indexLocation); //输出 0 arrayList.Add(1); //为了体现LastIndexOf的不同,先添加一个1 int lastLocation = arrayList.LastIndexOf(1); Console.WriteLine(lastLocation); //返回3 arrayList.Insert(2, "Insert插入的元素"); //这个方法与Add的不同在于它可以在任意位置插入 foreach (object obj in arrayList) { Console.Write(obj.ToString() + " "); //输出 1 你好 Insert插入的元素 3.265 1 } ArrayList arr = new ArrayList(); arr.Add(1); arr.Add(2); arrayList.AddRange(arr); foreach (object obj in arrayList) { Console.Write(obj.ToString() + "-"); //输出 1 你好 Insert插入的元素 3.265 1 1 2可以看到将一个新的集合追加到了最后 } arrayList.Remove(2); foreach (object obj in arrayList) { Console.Write(obj.ToString() + "-"); //输出 1 你好 Insert插入的元素 3.265 1 1 可以看到2已经被移除了 } Console.WriteLine(); arrayList.RemoveAt(0); foreach (object obj in arrayList) { Console.Write(obj.ToString() + "-"); //输出 你好 Insert插入的元素 3.265 1 1 可以看到第0个元素"2"已经被移除了 } Console.WriteLine(); //arrayList.Reverse(); //foreach (object obj in arrayList) //{ // Console.Write(obj.ToString() + "-"); //输出顺序倒转的所有元素 //} ArrayList AL3 = new ArrayList(); arrayList.SetRange(0,AL3); //从第0位开始,将元素复制到AL3中 foreach (object obj in AL3) { Console.Write(obj.ToString() + "-"); //输出 你好 Insert插入的元素 3.265 1 1 } object[] objArrs = new object[arrayList.Count]; objArrs = arrayList.ToArray(); foreach (object obj in objArrs) { Console.Write(obj.ToString() + "-"); } Console.WriteLine(); arrayList.Capacity = 5; //读取或设置可包含元素的数量,如果小于当前会报错。 Console.WriteLine(arrayList.Count); //输出5 arrayList.TrimToSize(); Console.WriteLine(arrayList.Count); //输出5 Console.ReadKey(); }
2、非泛型集合HashTable
Hashtable实现了IDictionary、ICollection以及IEnumerable接口。注意Hashtable,t是小写的。由于是非泛型集合,因此存储进去的都是object类型,不管是键还是值。
Hashtable的要点。
(1)、Hashtable仅有非泛型版本。
(2)、Hashtable类中的键不允许重复,但值可以。
(3)、Hashtable类所存储的键值对中,值可以为null,但键不允许为null。
(4)、Hashtable不允许排序操作。
以下给出一个实例,Hashtable提供的功能是在于ArraryList差不多,只不过存储的是键值对而已。只写个基本短小的示例。
C#中HashTable的用法
static void Main(string[] args) { Hashtable ht = new Hashtable(); ht.Add(1,1); ht.Add("我爱你","是吗?"); Console.WriteLine(ht.Count); //输出 2 Console.WriteLine(ht["我爱你"]); //输出 "是吗?" 用键 获取值 Console.WriteLine(ht.Contains(1)); //输出True Console.ReadKey(); }
3、Queue
和Queue<T>
Queue成为队列,队列是这样一种数据结构,数据有列表的一端插入,并由列表的另一端移除。就像单行道,只能从一段进,从一端出。Queue类实现了ICollection和IEnumerable接口。
Queue的一些重要特性。
1、先进先出
2、可以添加null值到集合中
3、允许集合中的元素重复
4、Queue容量会按需自动添加
5、Queue的等比因子是当需要更大容量时当前容量要乘以的数字,默认是2.0。
提供的功能都是差不多的,现在给出一个实例,主要显示Queue的作用:
static void Main(string[] args) { Queue q = new Queue(); q.Enqueue(1); q.Enqueue("想家了!"); q.Enqueue(1.23); Console.WriteLine(q.Peek()); //输出1 获取值但不移除,与出列不同 int Count = q.Count; //出队的时候q.Count在变化,因此q.Count放在循环条件里是不妥的 for (int i = 0; i < Count; i++) { Console.WriteLine(q.Dequeue().ToString()); //注意 输出 1 想家了 1.23 都是从最先添加的先拿 } Console.WriteLine(q.Count); //输出0 出列一次,就自动移除了。 Queue<int> qInt = new Queue<int>(); qInt.Enqueue(1); qInt.Enqueue(2); qInt.Enqueue(3); Console.WriteLine(qInt.Peek()); //输出1 int IntCount = qInt.Count; for (int i = 0; i < IntCount; i++) { Console.WriteLine(qInt.Dequeue()); //注意 输出 123 都是从最先添加的先拿 } Console.WriteLine(q.Count); //输出0 出列一次,就自动移除了。 Console.ReadKey(); }
4、Stack和Stack<T>
Stack称为栈,栈和队列非常相似,只不过队列是先进先出,而栈中的数据添加和移除都在一端进行,遵守栈中的数据则后进先出。Stack类实现了ICollection和IEnumerable接口。
Stack类的一些重要特性如下:
1、后进先出。
2、可以添加null值到集合中。
3、允许集合中的元素重复。
4、Stack的容量会按需自动增加。
列出几个有特点的功能:
static void Main(string[] args) { Stack s = new Stack(); s.Push(1); s.Push("想回家了!"); s.Push(1.23); Console.WriteLine(s.Peek()); //输出1.23 int Count = s.Count; //差点犯了逻辑错误,在for里面如果是s.Count的话,很容易乱,因为出栈操作s.Count是在变动着的。 for (int i = 0; i < Count; i++) { Console.WriteLine(s.Pop()); //输出 1.23 想回家了 1 } Console.WriteLine(s.Count); //输出0 Stack<int> sInt = new Stack<int>(); sInt.Push(1); sInt.Push(2); sInt.Push(3); Console.WriteLine(sInt.Peek()); //输出3 int IntCount = sInt.Count; //差点犯了逻辑错误,在for里面如果是s.Count的话,很容易乱,因为出栈操作s.Count是在变动着的。 for (int i = 0; i < IntCount; i++) { Console.WriteLine(sInt.Pop()); //输出 3 2 1 } Console.WriteLine(sInt.Count); //输出0 Console.ReadKey(); }
5、SortedList
与SortedList<T>
SortedList类实现了IDictionary、ICollection以及IEnumerable接口。SortedList类与HashTable类似,也表示一个键/值对集合,可以通过键和索引对元素进行访问,但不同的是,也是该类的最大作用所在,就是支持基于键的排序。在SortedList中,键和值分别保存在一个数组中,当向Sorted添加一个元素时,SortedList类添加一个元素时,SortedList会首先对key进行排序,然后根据排序结果计算出要插入到集合中的位置索引,再分别将key和value插入到各自数组的指定索引位置。当使用foreach循环集合中的元素时,SortedList会将相同索引位置的key和value放进一个DictionaryEntry类型的对象,然后返回。
C#集合之SortedList
static void Main(string[] args) { SortedList SL = new SortedList(); SL.Add("txt","txt"); //Add的时候会自动排序 SL.Add("jpg","jpg"); SL.Add("png","png"); foreach (DictionaryEntry de in SL) //返回的是DictionaryEntry对象 { Console.Write(de.Key + ":" + de.Value + " "); //输出 jpg:jpg png:png txt:txt //注意这个顺序啊,添加的时候就自动排序了 } Console.WriteLine(); SortedList<int,string> SLString = new SortedList<int,string>(); SLString.Add(3, "333"); SLString.Add(2, "222"); SLString.Add(1, "111"); foreach (KeyValuePair<int,string> des in SLString) //返回的是KeyValuePair,在学习的时候尽量少用var,起码要知道返回的是什么 { Console.Write(des.Key + ":" + des.Value + " "); } Console.ReadKey(); }
6、BitArray
BitArray类实现了一个位结构,它是一个二进制位(0和1)的集合。BitArray的值表示true或false。true表示位打开,false表示位关闭。BitArray实现了ICollection和IEnumerable接口。
BitArray的一些特性如下:
1、BitArray集合不支持动态调整,因此没有Add和Remove方法。
2、若需要调整集合的大小,可通过设置属性Length的值来实现。
3、集合中的索引从0开始。
4、使用BitArray(int length)构造函数初始化BitArray集合后,其值均为false。
5、BitArray集合之间支持按位“或”、“异或”、“与运算”,参与这三类运算的BitArray集合长度必须相等。否则会抛出异常。
static void Main(string[] args) { BitArray BA = new BitArray(3); BA[0] = true; BA[1] = false; BA[2] = true; BitArray BB = new BitArray(3); BA[0] = true; BA[1] = false; BA[2] = true; BitArray BOr = BA.Or(BB); //与运算,返回一个新的BitArray foreach (var b in BOr) { Console.Write(b + "-"); //True-False-True } Console.ReadKey(); }
7、Dictionary 字典
Dictionary<TKey, TValue>
中移除所有的键和值。 ContainsKey 确定 Dictionary<TKey, TValue>
是否包含指定的键。 ContainsValue 确定 Dictionary<TKey, TValue>
是否包含特定值。 Equals(Object) 确定指定的 Object 是否等于当前的 Object。 (继承自 Object。) Finalize 允许对象在“垃圾回收”回收之前尝试释放资源并执行其他清理操作。 (继承自 Object。) GetEnumerator 返回循环访问 Dictionary<TKey, TValue>
的枚举器。 GetHashCode 用作特定类型的哈希函数。 (继承自 Object。) GetObjectData 实现 System.Runtime.Serialization.ISerializable 接口,并返回序列化 Dictionary 实例所需的数据。 GetType 获取当前实例的 Type。 (继承自 Object。) MemberwiseClone 创建当前 Object 的浅表副本。 (继承自 Object。) OnDeserialization 实现 System.Runtime.Serialization.ISerializable 接口,并在完成反序列化之后引发反序列化事件。 Remove 从 Dictionary<TKey, TValue>
中移除所指定的键的值。 ToString 返回表示当前对象的字符串。 (继承自 Object。) TryGetValue 获取与指定的键相关联的值。 属性 Comparer 获取用于确定字典中的键是否相等的 IEqualityComparer<T>
。 Count 获取包含在 Dictionary<TKey, TValue>
中的键/值对的数目。 Item 获取或设置与指定的键相关联的值。 Keys 获取包含 Dictionary<TKey, TValue>
中的键的集合。 Values 获取包含 Dictionary<TKey, TValue>
中的值的集合。
//定义 Dictionary<string, string> openWith = new Dictionary<string, string>(); //添加元素 openWith.Add("txt", "notepad.exe"); openWith.Add("bmp", "paint.exe"); openWith.Add("dib", "paint.exe"); openWith.Add("rtf", "wordpad.exe"); //取值 Console.WriteLine("For key = \"rtf\", value = {0}.", openWith["rtf"]); //更改值 openWith["rtf"] = "winword.exe"; Console.WriteLine("For key = \"rtf\", value = {0}.", openWith["rtf"]); //遍历key foreach (string key in openWith.Keys) { Console.WriteLine("Key = {0}", key); } //遍历value foreach (string value in openWith.Values) { Console.WriteLine("value = {0}", value); } //遍历value, Second Method Dictionary<string, string>.ValueCollection valueColl = openWith.Values; foreach (string s in valueColl) { Console.WriteLine("Second Method, Value = {0}", s); }//遍历字典 foreach (KeyValuePair<string, string> kvp in openWith) { Console.WriteLine("Key = {0}, Value = {1}", kvp.Key, kvp.Value); } //添加存在的元素 try { openWith.Add("txt", "winword.exe"); } catch (ArgumentException) { Console.WriteLine("An element with Key = \"txt\" already exists."); } //删除元素 openWith.Remove("doc"); if (!openWith.ContainsKey("doc")) { Console.WriteLine("Key \"doc\" is not found."); } //判断键存在 if (openWith.ContainsKey("bmp")) // True { Console.WriteLine("An element with Key = \"bmp\" exists."); } //参数为其它类型 Dictionary<int, string[]> OtherType = new Dictionary<int, string[]>(); OtherType.Add(1, "1,11,111".Split(',')); OtherType.Add(2, "2,22,222".Split(',')); Console.WriteLine(OtherType[1][2]); //参数为自定义类型 //首先定义类 class DouCube { public int Code { get { return _Code; } set { _Code = value; } } private int _Code; public string Page { get { return _Page; } set { _Page = value; } } private string _Page; } //声明并添加元素 Dictionary<int, DouCube> MyType = new Dictionary<int, DouCube>(); for (int i = 1; i <= 9; i++) { DouCube element = new DouCube(); element.Code = i * 100; element.Page = "http://www.doucube.com/" + i.ToString() + ".html"; MyType.Add(i, element); } //遍历元素 foreach (KeyValuePair<int, DouCube> kvp in MyType) { Console.WriteLine("Index {0} Code:{1} Page:{2}", kvp.Key, kvp.Value.Code, kvp.Value.Page); }
- c# 集合对象详解
- c# 集合对象详解
- C#集合详解
- C#集合详解
- C#中 集合的使用详解
- C#中的ArrayList集合详解与深度探讨
- C#集合
- C# 集合
- C#集合
- C#集合
- c#集合
- C# 集合
- C#集合
- C#集合
- C#集合
- C#集合
- C#集合
- c#集合
- 计算机图形学——边缘填充算法和边界填充算法
- Integer equals 和 == 比较
- hdu 2222 Keywords Search(AC自动机)
- MVC框架与DAL的查询与模糊查询
- 小强学AI之
- C#集合详解
- wpa_supplicant无线网络配置
- Linux 设置永久ip地址的方法
- checkList
- MyEclipse+Tomcat+MAVEN+SVN项目完整环境搭建
- 51Nod 1049 最大子段和【简单dp】
- Java 中list和map遍历删除
- !!!重要!!!Spring———— IOC的底层原理
- MTK Fuel Gauge算法分析