C#集合基础与运用
C#集合基础与运用
转至:http://www.cnblogs.com/LiZhiW/p/3539839.html
1.集合接口与集合类型
(1)集合的命名空间
大多数集合类都可以在 System.Collections 和 System.Collections.Generic 名称空间中找到。
泛型集合位于System.Collections.Generic 名称空间中;
专用于特定类型的集合类位于System.Collections.Specialized名称空间中;
线程安全的集合位于System.Collections.Concurrent名称空间中。
(2)集合接口介绍
1、IEnumerable 与IEnumerator 接口
其实IEnumerable接口是非常的简单,只包含一个抽象的方法GetEnumerator(),它返回一个可用于循环访问集合的IEnumerator对象。
public interface IEnumerable
{
IEnumerator GetEnumerator();
}
IEnumerator对象有什么呢?
它是一个真正的集合访问器,没有它,就不能使用foreach语句遍历集合或数组,因为只有IEnumerator对象才能访问集合中的项。
IEnumerator接口定义了:一个Current属性用来获取当前集合中的项;MoveNext方法将游标的内部位置向前移动;Reset方法将枚举数设置为其初始位置,该位置位于集合中第一个元素之前。
public interface IEnumerator { object Current { get; } bool MoveNext(); void Reset(); }
一个collection要支持foreach进行遍历,就必须实现IEnumerable,并以某种方式返回迭代器对象:IEnumerator。
2、集合和列表实现的接口表
接口 |
说明 |
IEnumerable<T> |
如果foreach语句用于集合,就需要此接口。 |
ICollection<T> |
此集合定义了Count属性、CopyTo、Add、Remove、Clear方法 |
IList<T> |
可以通过位置访问几何元素 |
ISet<T> |
此集合不允许有重复的元素 |
IDictionary<K,V> |
含有键值对的集合 |
ILookup<K,V> |
含有键值对的集合,但可以通过一个键包含多个值 |
IComparer<T> |
集合元素比较器,用于集合元素的排序 |
IEqualityComparer<T> |
用于字典集合的比较器 |
IProducerConsumerCollection<T> |
线程安全的集合 |
2.集合的基本操作
using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace CollectionDemo { class Program { static void Main(string[] args) { #region 1、集合的基本操作 //1)、创建集合 //CreateCollection(); //2)、添加元素至集合 //AddCollection(); //3)、插入元素至集合 //InsertCollection(); //4)、访问集合中的元素 //VisitCollection(); //5)、遍历集合 //IteratesCollection(); //6)、删除集合中的元素 //DeleteCollection(); //7)、查找元素 //FindCollection(); //8)、集合排序 //SortCollection(); //9)、集合数据类型转换 //ConvertCollection(); //11)、集合常见扩展方法Select //SelectCollection(); //12)、集合常见扩展方法Where //WhereCollection(); #endregion 集合的基本操作 #region 2、常见集合的特性 //队列(Queue) //QueueCollection(); //栈(Stack) //StackCollection(); //链表(LinkedList) //LinkedCollection(); //有序列表(SortedList<K,V>) //SortedListCollection(); //字典 Lookup //LookupCollection(); #endregion 常见集合的特性 } #region 1、集合的基本操作 /// <summary> /// 1)、创建集合 /// 使用默认的构造函数创建一个空集合,元素添加到集合之后,集合的容量就会扩大为4。 /// 当集合的容量被使用完,且还在向集合中添加元素时,集合的容量就会扩大成原来的2倍! /// 可使用Capacity属性设置或访问集合的容量,使用Count属性访问集合的元素个数。 /// 也可使用TrimExcess方法调整集合容量,节省内存! /// </summary> public static void CreateCollection() { List<int> list = new List<int>(); //List<int> list = new List<int>(3); //指定初始容量 //创建集合时可以为集合设置初始值 如下: //List<int> list1 = new List<int>() { 1,2,3,4,5,6,7,8,9,0}; //List<string> list2 = new List<string>() { "aa", "bb", "cc" }; for (int i = 0; i < 1025; i++) { if (list.Count == list.Capacity) { Console.WriteLine("容量使用量:" + list.Count + "/" + list.Capacity); } list.Add(i); Console.WriteLine("容量使用量:" + list.Count + "/" + list.Capacity); } Console.WriteLine("容量使用量:" + list.Count + "/" + list.Capacity); list.TrimExcess(); //整集合容量 Console.WriteLine("容量使用量:" + list.Count + "/" + list.Capacity); Console.Read(); } /// <summary> /// 2)、添加元素集合 /// 为集合添加元素可使用Add方法,还可以使用AddRange方法一次添加多个元素, /// 因为AddRange方法的参数是IEnumerable<T>类型的对象,所以可以添加数组到集合里。 /// </summary> public static void AddCollection() { List<string> list = new List<string>(); list.AddRange(new string[] { "bb", "cc", "dd" }); //添加数组 list.AddRange(list); list.Add("aa"); foreach (string item in list) { Console.WriteLine(item); } Console.Read(); } /// <summary> /// 3)、插入元素至集合 /// 插入元素可以使用Insert方法,同样使用InsertRange方法插入多个元素 /// </summary> public static void InsertCollection() { List<string> list = new List<string>() { "aa", "bb","ff" }; list.Insert(2, "cc"); //插入元素 list.InsertRange(3, new string[] { "dd", "ee" }); //插入集合 foreach (string item in list) { Console.WriteLine(item); } Console.Read(); } /// <summary> /// 4)、访问集合中的元素 /// 使用索引器访问集合中某个位置的元素 /// </summary> public static void VisitCollection() { List<string> list = new List<string>() { "aa", "bb", "cc", "ee" }; Console.WriteLine(list[1]); //访问第1个位置上的元素,下标从0开始 Console.Read(); } /// <summary> /// 5)、遍历集合 /// 集合的遍历,除了使用for、foreach外,还可以使用集合的Foreach方法, /// 该方法的参数是一个Action<T>委托类型,可以使用Lambda表达式 /// </summary> public static void IteratesCollection() { List<string> list = new List<string>() { "aa", "bb", "cc" }; list.ForEach(tmp => Console.WriteLine("元素:" + tmp)); //也可以这样使用:list.ForEach(Console.WriteLine); Console.Read(); } /// <summary> /// 6)、删除集合中的元素 /// 使用RemoveAt删除指定位置的元素,使用Remove删除指定的元素, /// 使用RemoveRange删除指定位置范围的元素,使用Clear删除所有元素 /// 使用RemoveAll选择删除的元素。注意:RemoveAll方法的参数是一个Predicate<T>委托类型 /// </summary> public static void DeleteCollection() { List<string> list = new List<string>() { "12", "123", "1234", "12345" }; //删除长度小于4的元素 list.RemoveAll(x => { bool flag = x.Length < 4; return flag; }); list.ForEach(Console.WriteLine); Console.Read(); } /// <summary> /// 7)、查找元素 /// 用于搜索的方法有:IndexOf、LastIndexOf、FindIndex、FindLastIndex、FindLast、Find、FindAll、Exists等方法。 /// IndexOf、LastIndexOf、FindIndex、FindLastIndex 方法用于搜索元素的位置。 /// FindLast、Find、FindAll 方法用于搜索满足条件的元素。 /// Exists 用于判断集合是否存在某些元素。 /// 参数可以使用Predicate<T>委托类型(Lambda表达式)的方法有:FindIndex、FindLastIndex、Find、FindLast、FindAll、Exists。 /// </summary> public static void FindCollection() { List<string> list = new List<string>() { "12", "123", "1234", "12345" }; list = list.FindAll(x => { bool flag = x.Length < 4; return flag; }); list.ForEach(Console.WriteLine); Console.Read(); } /// <summary> /// 8)、元素排序 /// 可以使用Sort方法对元素排序,也可以调用Reverse方法逆转集合顺序,Sort方法使用快速排序算法 /// Sort使用了几个重载的方法,可以传递的参数有泛型委托Comparison<T>和泛型接口IComparer<T> /// </summary> public static void SortCollection() { List<string> list = new List<string>() { "12", "123", "1234", "12345" }; //按字符串长度排序 list.Sort((x, y) => { return y.Length - x.Length; }); list.ForEach(Console.WriteLine); Console.Read(); #region Sort例子 /* // 把Student继承IComparer<Student>, IComparable<Student> 这两个接口,List<Student>就可以Sort了 public class Student : IComparer<Student>, IComparable<Student> { public string name; public int num; //下面是一些方法及属性 public int Compare(Student s1, Student s2) { if (s1.num > s2.num) return 1; if (s1.num < s2.num) return -1; return 0; } public int CompareTo(Student s) { return Compare(this, s); } } //测试 List<Student> l = new List<Student>(); Student s1 = new Student(); s1.num = 5; Student s2 = new Student(); s2.num = 3; Student s3 = new Student(); s3.num = 6; l.Add(s1); l.Add(s2); l.Add(s3); l.Sort(); */ #endregion Sort例子 } /// <summary> /// 9)、集合类型转换 /// 使用ConvertAll<TOutput>方法可以把集合里的所有元素转换成另一种类型,ConvertAll<TOutput>使用了Converter委托,其定义如下: /// public sealeddelegate TOutput Converter<TInput, TOutput>(TInput from) /// TInput是委托方法的参数类型,TOutput是委托方法的返回值类型。例如: /// </summary> public static void ConvertCollection() { List<string> list = new List<string>() { "12", "123", "1234", "12345" }; //把字符串集合转换成数字集合 List<int> array = list.ConvertAll<int>(tmp => Int32.Parse(tmp)); array.ForEach(Console.WriteLine); Console.Read(); } //10)、只读集合 //集合的AsReadOnly方法可以返回一个ReadOnlyCollection<T>类型的集合; //ReadOnlyCollection<T>是一个只读集合类型,除了不能使用修改集合的方法与属性,其它与集合一样。 /// <summary> /// 11)、集合常用的扩展方法[Select] /// Select:将序列中的每个元素投影到新表中 /// </summary> public static void SelectCollection() { List<int> list = new List<int>() { 1, 3, 5, 7, 9 }; IEnumerable<string> array = list.Select<int, string>(x => (x * x).ToString()); foreach (string s in array) { Console.WriteLine(s); } Console.Read(); } /// <summary> /// 12)、集合常用的扩展方法[Where] /// Where:基于谓词筛选值序列 /// </summary> public static void WhereCollection() { List<string> list = new List<string> { "1", "12", "123", "1234" }; //查询长度小于3的元素 IEnumerable<string> query = list.Where(temp => temp.Length < 3); foreach (string s in query) { Console.WriteLine(s); } Console.Read(); } #endregion 集合的基本操作 #region 2、常见集合的特性 //(1)非泛型集合对应的泛型集合 // 非泛型集合类 对应的泛型集合类 // ArrayList List<T> // HashTable DIctionary<T> // Queue Queue<T> // Stack Stack<T> // SortedList SortedList /// <summary> /// 1、队列(Queue) /// 队列是其元素以先进先出的方式来处理的集合。该集合没有Add与Remove方法,其重要的方法: /// Enqueue():在队列的尾端添加元素 /// Dequeue():在队列的头部读取并删除元素 /// Peek() :只读取队列头部的元素 /// </summary> public static void QueueCollection() { Queue<string> queue = new Queue<string>(); for (int i = 0; i < 5; i++) { queue.Enqueue(i.ToString());//在尾部添加元素 } PrintQueue(queue);//输出元素 string s = queue.Dequeue(); //读取并删除头部元素 Console.WriteLine("读取并删除头部元素:" + s); queue.Enqueue("5"); //在尾部添加元素 s = queue.Peek(); //读取头部元素 Console.WriteLine("读取头部元素:" + s); PrintQueue(queue);//输出元素 Console.Read(); } private static void PrintQueue(Queue<string> q) { IEnumerable<string> list = q.Where(t => true); foreach (string s in list) { Console.WriteLine(s); } } /// <summary> /// 2、栈(Stack<T>) /// 栈是一个后进先出的容器,其重要的方法: /// Push() :在栈顶压入一个元素入栈 /// Pop() :从栈顶读取并删除一个元素 /// Peek() :只从栈顶读取一个元素而不删除 /// </summary> public static void StackCollection() { Stack<string> stack = new Stack<string>(); for (int i = 0; i < 5; i++) { stack.Push(i.ToString()); //入栈 } PrintStack(stack); //输出 string s = stack.Pop(); //读取并删除栈顶元素 Console.WriteLine("读取并删除栈顶元素:" + s); s = stack.Peek(); Console.WriteLine("只读取栈顶元素:" + s); PrintStack(stack); Console.Read(); } private static void PrintStack(Stack<string> stack) { IEnumerable<string> list = stack.Where(t => true); foreach (var t in list) { Console.WriteLine(t); } } /// <summary> /// 3、链表(LinkedList<T>) /// LinkedList<T>是一个双向链表。 /// 链表的优点是,如果将元素插入列表的中间位置,使用链表就会非常快,只需要修改下一个元素的Next引用与上一个元素的Previous引用。 /// 链表不能在集合中只存储元素,必须要把元素存到LinkedListNode<T>类型的对象中,LinkedListNode<T>定义了属性:List、Next、Value、Previous。 /// List属性返回与该节点相关的LinkedList<T>对象,Next、Previous用于遍历链表。 /// /// LinkedList<T>对象可以访问第一个和最后一个元素(Frist与Last)、 /// 在指定位置插入元素(AddAfter()、AddBefore()、AddFirst()、AddLast()方法), /// 删除指定位置的元素(ReMove()、ReMoveFirst()、RemoveLast()方法), /// 从链表的开头(Find())或结尾(FindLast())开始搜索元素。 /// </summary> public static void LinkedCollection() { LinkedList<int> link = new LinkedList<int>(); LinkedListNode<int> node; for (int i = 0; i < 10; i++) { node = new LinkedListNode<int>(i); if (i % 2 == 0) { link.AddFirst(node); //从头部添加节点 } else { link.AddLast(node);//从尾部添加节点 } } PrintLink(link); //输出元素 Console.Read(); } private static void PrintLink(LinkedList<int> link) { IEnumerable<int> list = link.Where(t => true); foreach (int t in list) { Console.WriteLine(t); } } /// <summary> /// 4、有序列表(SortedList<K,V>) /// SortedList<K,V>是基于键对集合进行排序的集合类,它只允许每个键只有一个对应值,如果需要每个键对应多个值可以使用Lookup<K,V>。 /// 可以使用foreach遍历该集合,枚举器返回的是KeyValuePair<K,V>类型的元素。 /// 除了使用Add方法添加元素,还可以使用索引器添加。 /// </summary> public static void SortedListCollection() { SortedList<string, string> sort = new SortedList<string, string>(); sort.Add("K1", "K1的值"); //Add方法添加元素 sort["K2"] = "K2的值"; //索引器添加元素 PrintSorted(sort); Console.WriteLine("是否存在[K3]:" + sort.ContainsKey("K3")); string value = null; Console.WriteLine("是否存在[K2]:" + sort.TryGetValue("K2",out value)); Console.WriteLine("[K2的值]:" + value); Console.Read(); } private static void PrintSorted(SortedList<string, string> sort) { IEnumerable<KeyValuePair<string, string>> list = sort.Where(tmp => true); foreach (KeyValuePair<string,string> item in list) { Console.WriteLine(item.Key + " ----> " + item.Value); } } //5、字典 /* * 字典中键的类型必须重写Object类的GetHashCode()方法。 * 只要字典类需要确定元素的位置,他就会调用GetHashCode()方法。除了实现GetHashCode()方法外,键类型还必须实现IEquatable<T>.Equals()方法,或重写Object类的Equals()方法。 * 因为不同的对象可能返回相同的散列码(GetHashCode方法返回值),但是如果A.Equals(B)返回true,则A和B的散列码就必须相同。 * 这似乎有点奇怪,但这非常重要,因为字典的性能取决于GetHashCode()方法实现的代码。 */ //字典1): Dictionary<K,V> // Dictionary<K,V>类支持每个键关联一个值,与SortedList<K,V>很类似,具体参考SortedList<K,V>。 /// <summary> /// 字典2):Lookup<K,V> /// Lookup<K,V>类把键映射到一个值集上。 /// 创建Lookup<K,V>类对象必须调用ToLookup()扩展方法,该方法返回一个Lookup<K,V>对象。 /// ToLookup()方法需要一个Func<T,K>类型的委托参数,Func<T,K>类型定义了键的选择器。 /// ToLookup()用于对一个集合进行操作,创建一个1:n 的映射。 它可以方便的将数据分类成组,并生成一个字典供查询使用。 /// </summary> public static void LookupCollection() { List<string> list = new List<string>() { "1", "12", "123", "1234", "a", "ab", "abc" }; var lookup = list.ToLookup(x => x.Length); foreach (var t in lookup) { List<string> temp = t.ToList<string>(); //把一组数据转换成集合 temp.ForEach(x => Console.Write(x + "、")); //输出集合 Console.WriteLine(); } Console.Read(); } /* * 字典3):SortedDictionary<K,V> * SortedDictionary<K,V>类是一个二叉搜索树,其中的元素根据键来排序,该键类型必须实现IComparable<T>接口。 * SortedDictionary<K,V>与SortedList<K,V>的区别: * SortedList<K,V>类使用的内存比SortedDictionary<K,V>少。 * SortedDictionary<K,V>类的元素的插入与删除比较快。 * 在用于已排好序的集合,若不需要修改容量SortedList<K,V>会比较快。 * 区别的根本原因:SortedList<K,V>实现的是一个基于数组的集合,SortedDictionary<K,V>实现的是一个基于字典的集合。 */ //6、集(ISet<T>接口) //不包含重复元素的集合称为集,.NET Framework包含两个集(HashSet<T>和SortedSet<T>),它们都实现ISet<T>接口。 //HashSet<T>是不包含重复元素的无序列表,SortedSet<T>是不包含重复元素的有序列表。 #endregion 常见集合的特性 } }