在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
什么是集合(collection)? 提供了一种结构化组织任意对象的方式,从.NET 的角度看,所谓的集合可以定义为一种对象,这种对象实现一个或者多个System.Collections.ICollection、 System.Collections.IDictionary和System.Collections.IList接口。这一定义把 System.Collections名称空间中的“内置”集合划分成了三种类别: * 有序集合:仅仅实现ICollection接口的集合,在通常情况下,其数据项目的插入顺序控制着从集合中取出对象的的顺序。 System.Collections.Stack和 System.Collections.Queue类都是ICollection集合的典型例子。 以OOP (面向对象编程)的术语来说,上面以接口这种方式构造对象的功能,就是多态技术。 System.Collections 命名空间包含接口和类,这些接口和类定义各种对象(如列表、队列、位数组、哈希表和字典)的集合。 在System.Collections命名空间中提供了许多接口:
什么是ArrayList? 一种正常数组和集合的混合类型(动态数组,就是Array的复杂版本) 优点:动态的增加和减少元素 实现了ICollection和IList接口 灵活的设置数组的大小 缺点:ArrayList负载比传统数组更大而且没有实现严格的类型化,也就可以接受任何转换为System.Object的对象,存在类型安全和效率问题(面试点) 如何使用ArrayList 1 ArrayList al = new ArrayList(); 2 al.Add(100);//单个添加 3 foreach (int number in new int[6] { 9, 3, 7, 2, 4, 8 }) 4 { 5 al.Add(number);//集体添加方法一 6 } 7 al.AddRange(new int[2] { 11, 12 });//集体添加方法二 8 ArrayList al2 = new ArrayList(al.GetRange(1, 3));//新ArrayList只取一部份 9 foreach (int i in al)//不要强制转换 10 { 11 Console.WriteLine(i); 12 } 13 for (int i = 0; i < al2.Count; i++)//数组是length 14 { 15 int number = (int)al2[i];//一定要强制转换 16 Console.WriteLine(number); 17 } 18 IEnumerator ie=al.GetEnumerator(); 19 while(ie.MoveNext()) 20 { 21 Console.Write(ie.Curret.ToString()+" "); 22 } 23 Int32[] values = (Int32[])al.ToArray(typeof(Int32));//返回ArrayList包含的数组 24 View Code ArrayList重要的方法和属性 1 public ArrayList() 2 { 3 this._items = emptyArray; 4 } 5 public ArrayList(ICollection c) 6 { 7 if (c == null) 8 { 9 throw new ArgumentNullException("c", Environment.GetResourceString("ArgumentNull_Collection")); 10 } 11 int count = c.Count; 12 if (count == 0) 13 { 14 this._items = emptyArray; 15 } 16 else 17 { 18 this._items = new object[count]; 19 this.AddRange(c); 20 } 21 } 22 public ArrayList(int capacity) 23 { 24 if (capacity < 0) 25 { 26 throw new ArgumentOutOfRangeException("capacity", Environment.GetResourceString("ArgumentOutOfRange_MustBeNonNegNum", new object[] { "capacity" })); 27 } 28 if (capacity == 0) 29 { 30 this._items = emptyArray; 31 } 32 else 33 { 34 this._items = new object[capacity]; 35 } 36 } public override int Add(object obj) 37 { 38 int num = this._list.Add(obj); 39 base._version++; 40 return num; 41 } IsSynchronized属性,ArrayList.Synchronized方法 但是,使用这个方法(ArrayList.Synchronized)并不能保证枚举的同步,例如,一个线程正在删除或添加集合项,而另一个线程同时进行枚举,这时枚举将会抛出异常。所以,在枚举的时候,你必须明确使用 SyncRoot 锁定这个集合。 ArrayList与数组转换 1 ArrayList List = new ArrayList(); 2 List.Add(1); 3 List.Add(2); 4 List.Add(3); 5 Int32[] values = (Int32[])List.ToArray(typeof(Int32)); 6 7 ArrayList List = new ArrayList(); 8 List.Add(1); 9 List.Add(2); 10 List.Add(3); 11 Int32[] values = new Int32[List.Count]; 12 List.CopyTo(values); 13 14 15 //往数组中添加不同类型的元素 16 ArrayList List = new ArrayList(); 17 List.Add( “string” ); 18 List.Add( 1 ); 19 object[] values = List.ToArray(typeof(object)); //正确 20 string[] values = (string[])List.ToArray(typeof(string)); //错误 ArrayList最佳使用建议 队列(Queue)和栈(Stack): System.Collections.Stack 和 System.Collections.Queue 类,两者仅仅实现了ICollection 接口,按照存储项目加到集合的顺序保存System.Object类型的项目。对象只能按其加入顺序从集合中检索:堆栈是后进先出,而队列则是先进先出。通常情况下,你在以下场合可以考虑采用以上这些集合: * 接收和处理集合内项目时顺序比较重要。 1 队列 2 Queue qu = new Queue(); 3 Queue qu2 = new Queue(); 4 foreach (int i in new int[4] { 1, 2, 3, 4 }) 5 { 6 qu.Enqueue(i);//入队 7 qu2.Enqueue(i); 8 } 9 10 foreach (int i in qu) 11 { 12 Console.WriteLine(i);//遍历 13 } 14 15 qu.Dequeue();//出队 16 Console.WriteLine("Dequeue"); 17 foreach (int i in qu) 18 { 19 Console.WriteLine(i); 20 } 21 22 qu2.Peek();//返回位于 Queue 开始处的对象但不将其移除。 23 Console.WriteLine("Peek"); 24 foreach (int i in qu2) 25 { 26 Console.WriteLine(i); 27 } 28 29 栈 30 Stack sk = new Stack(); 31 Stack sk2 = new Stack(); 32 foreach (int i in new int[4] { 1, 2, 3, 4 }) 33 { 34 sk.Push(i);//入栈 35 sk2.Push(i); 36 } 37 38 foreach (int i in sk) 39 { 40 Console.WriteLine(i);//遍历 41 } 42 43 sk.Pop();//出栈 44 Console.WriteLine("Pop"); 45 foreach (int i in sk) 46 { 47 Console.WriteLine(i); 48 } 49 50 sk2.Peek();//弹出最后一项不删除 51 Console.WriteLine("Peek"); 52 foreach (int i in sk2) 53 { 54 Console.WriteLine(i); 55 } HashTable: System.Collections.HashTable集合实现了IDictionary 和 Icollection,能用来存储多种类型的对象连同关联的唯一字符串键值。在HashTable集合中的项目按照源自其键值的哈希代码所确定的顺序存储。集合内每个对象的键值都必须唯一,而其哈希代码则不一定唯一。 从性能的角度看,因为键值搜索仅限于具有同样哈希代码的键值,所以HashTable能够很快地从集合中检索任意一个元素,从而减少了必须通过检查以发现匹配的键值的数量。然而,因为插入到集合中的每个对象-键值对都必须产生相应的哈希代码,所以项目插入的代价就有点高了。因此,HashTable 主要运用在按照任意键值反复检索大量相对静态的数据这一场合下 Add方法参数都是object类型 对哈希表进行排序 Console.WriteLine(ht[skey]);//排序后输出
} 1 Hashtable ht = new Hashtable(); //创建一个Hashtable实例 2 ht.Add("E", "e");//添加key/value键值对 3 ht.Add("A", "a"); 4 ht.Add("C", "c"); 5 ht.Add("B", "b"); 6 string s = (string)ht["A"]; 7 if (ht.Contains("E")) //判断哈希表是否包含特定键,其返回值为true或false 8 Console.WriteLine("the E key:exist"); 9 ht.Remove("C");//移除一个key/value键值对 10 Console.WriteLine(ht["A"]);//此处输出a 11 ht.Clear();//移除所有元素 12 Console.WriteLine(ht["A"]); //此处将不会有任何输出 13 Console.ReadKey(); NameValueCollection: System.Collections.Specialized.NameValueCollection 最有趣的地方在于它能包含关联同一键值的多个项目(允许出现相同的键,值会用逗号连起来),这正是它与其他内建集合的差别所在。除此以外,它在功能上类似HashTable,按照源自每一项目键值的哈希代码对项目排序从而也具有类同的优缺点。用处:写自定义控件存储键值一般用这个 ListDictionary 和 HybridDictionary: ListDictionary 和 HybridDictionary 类归属于System.Collections.Specialized。它们都在按照唯一键值的原则来组织项目,而且都实现了 IDictionary 和 ICollection 。ListDictionary在内部以链表的方式存储项目,建议用在不会增长超过10个项目的集合中。HybridDictionary采用一个内部链 表(实际上就是ListDictionary)作为小集合,当集合变得足够大(超过10个项目)以至于链表实现效率降低时就会转换为HashTable。 StringCollection 和 StringDictionary: System.Collections.Specialized.StringCollection 和 System.Collections.Specialized.StringDictionary 都对存储字符串的集合进行了优化。 StringCollection实现了 IList 和 ICollection 而且实质上就是ArrayList,只不过实现了强烈的类型化仅仅接受字符串而已。StringCollection最理想的应用场合是经常更新或增加的 少量数据,而StringDictionary则最适用于不经常增加项目到诸如HashTable之类集合中的大量数据。 SortedList: System.Collections.SortedList,它实现了IDictionary和ICollection接口,是最基本的排序集 合,与Vb6下的Collection对象非常类似。 SortedList存储对象并按照关联的键值对这些存储对象排序。它们也是同时支持索引数字和键对象检索的唯一内建的.NET集合,与哈希表类似,区别在于SortedList中的Key数组排好序的 1 SortedList sl = new SortedList(); 2 sl["c"] = 41; 3 sl["a"] = 42; 4 sl["d"] = 11; 5 sl["b"] = 13; 6 7 foreach (DictionaryEntry element in sl) 8 { 9 string s = (string)element.Key; 10 int i = (int)element.Value; 11 Console.WriteLine("{0},{1}", s, i); 12 } Dictionary 泛型集合 泛型最常见的用途是泛型集合,命名空间System.Collections.Generic 中包含了一些基于泛型的集合类,使用泛型集合类可以提供更高的类型安全性,还有更高的性能,避免了非泛型集合的重复的装箱和拆箱。
很多非泛型集合类都有对应的泛型集合类,下面是常用的非泛型集合类以及对应的泛型集合类:
我们用的比较多的非泛型集合类主要有 ArrayList类 和 HashTable类。我们经常用HashTable 来存储将要写入到数据库或者返回的信息,在这之间要不断的进行类型的转化,增加了系统装箱和拆箱的负担,如果我们操纵的数据类型相对确定的化 用 Dictionary<TKey,TValue> 集合类来存储数据就方便多了,例如我们需要在电子商务网站中存储用户的购物车信息( 商品名,对应的商品个数)时,完全可以用 Dictionary<string, int> 来存储购物车信息,而不需要任何的类型转化。
下面是简单的例子,包括声明,填充键值对,移除键值对,遍历键值对 1 Dictionary<string, string> myDic = new Dictionary<string, string>(); 2 myDic.Add("aaa", "111"); 3 myDic.Add("bbb", "222"); 4 myDic.Add("ccc", "333"); 5 myDic.Add("ddd", "444"); 6 //如果添加已经存在的键,add方法会抛出异常 7 try 8 { 9 myDic.Add("ddd", "ddd"); 10 } 11 catch (ArgumentException ex) 12 { 13 Console.WriteLine("此键已经存在:" + ex.Message); 14 } 15 //解决add()异常的方法是用ContainsKey()方法来判断键是否存在 16 if (!myDic.ContainsKey("ddd")) 17 { 18 myDic.Add("ddd", "ddd"); 19 } 20 else 21 { 22 Console.WriteLine("此键已经存在:"); 23 24 } 25 26 //而使用索引器来负值时,如果建已经存在,就会修改已有的键的键值,而不会抛出异常 27 myDic["ddd"] = "ddd"; 28 myDic["eee"] = "555"; 29 30 //使用索引器来取值时,如果键不存在就会引发异常 31 try 32 { 33 Console.WriteLine("不存在的键\"fff\"的键值为:" + myDic["fff"]); 34 } 35 catch (KeyNotFoundException ex) 36 { 37 Console.WriteLine("没有找到键引发异常:" + ex.Message); 38 } 39 //解决上面的异常的方法是使用ContarnsKey() 来判断时候存在键,如果经常要取健值得化最好用 TryGetValue方法来获取集合中的对应键值 40 string value = ""; 41 if (myDic.TryGetValue("fff", out value)) 42 { 43 Console.WriteLine("不存在的键\"fff\"的键值为:" + value); 44 } 45 else 46 { 47 Console.WriteLine("没有找到对应键的键值"); 48 } 49 50 //下面用foreach 来遍历键值对 51 //泛型结构体 用来存储健值对 52 foreach (KeyValuePair<string, string> kvp in myDic) 53 { 54 Console.WriteLine("key={0},value={1}", kvp.Key, kvp.Value); 55 } 56 //获取值得集合 57 foreach (string s in myDic.Values) 58 { 59 Console.WriteLine("value={0}", s); 60 } 61 //获取值得另一种方式 62 Dictionary<string, string>.ValueCollection values = myDic.Values; 63 foreach (string s in values) 64 { 65 Console.WriteLine("value={0}", s); 66 }
|
请发表评论