zoukankan      html  css  js  c++  java
  • c#基础语言编程-集合

    引言

    在c#常用的集合分为非泛型集合和泛型集合。
    非泛型集合的类和接口位于System.Collections命名空间。这些接口和类定义各种对象(如列表、队列、位数组、哈希表和字典)的集合。
    泛型集合的类和接口位于System.Collections.Generic命名空间。命名空间包含定义泛型集合的接口和类,泛型集合允许用户创建强类型集合,它能提供比非泛型强类型集合更好的类型安全性和性能。
    System.Collections.Specialized 命名空间包含专用的和强类型的集合,例如,链接的列表词典、位向量以及只包含字符串的集合。
    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具体提供的功能

    属性              说明

    Capacity             获取或设置 ArrayList 可包含的元素数。
    Count              获取 ArrayList 中实际包含的元素数。
    IsFixedSize            获取一个值,该值指示 ArrayList 是否具有固定大小。
    IsReadOnly            获取一个值,该值指示 ArrayList 是否为只读。
    IsSynchronized          获取一个值,该值指示是否同步对 ArrayList 的访问(线程安全)。
    Item               获取或设置指定索引处的元素。
    SyncRoot             获取可用于同步 ArrayList 访问的对象。

    方法

    Adapter              为特定的 IList 创建 ArrayList 包装。
    Add                将对象添加到 ArrayList 的结尾处。
    AddRange             将 ICollection 的元素添加到 ArrayList 的末尾。
    BinarySearch           已重载。 使用对分检索算法在已排序的 ArrayList 或它的一部分中查找特定元素。
    Clear               从 ArrayList 中移除所有元素。
    Clone               创建 ArrayList 的浅表副本。
    Contains             确定某元素是否在 ArrayList 中。
    CopyTo              已重载。 将 ArrayList 或它的一部分复制到一维数组中。
    FixedSize             已重载。 返回具有固定大小的列表包装,其中的元素允许修改,但不允许添加或移除。
    GetEnumerator          已重载。 返回循环访问 ArrayList 的枚举数。
    GetRange             返回 ArrayList,它表示源 ArrayList 中元素的子集。
    IndexOf             已重载。 返回 ArrayList 或它的一部分中某个值的第一个匹配项的从零开始的索引。
    Insert               将元素插入 ArrayList 的指定索引处。 可在任意位置插入。
    InsertRange            将集合中的某个元素插入 ArrayList 的指定索引处。
    LastIndexOf            已重载。 返回 ArrayList 或它的一部分中某个值的最后一个匹配项的从零开始的索引。
    ReadOnly             已重载。 返回只读的列表包装。
    Remove             从 ArrayList 中移除特定对象的第一个匹配项。
    RemoveAt           移除 ArrayList 的指定索引处的元素。
    RemoveRange          从 ArrayList 中移除一定范围的元素。
    Repeat              返回 ArrayList,它的元素是指定值的副本。
    Reverse             已重载。 将 ArrayList 或它的一部分中元素的顺序反转。
    SetRange             将集合中的元素复制到 ArrayList 中一定范围的元素上。
    Sort               已重载。 对 ArrayList 或它的一部分中的元素进行排序。
    Synchronized         已重载。 返回同步的(线程安全)列表包装。
    ToArray             已重载。 将 ArrayList 的元素复制到新数组中。
    TrimToSize            将容量设置为 ArrayList 中元素的实际数目。

    要知道,集合中有两个属性,其一是该集合的容量Capacity,其二是集合中拥有元素的个数Count。这两者并不对等的。集合的容量是表示该集合中能容纳的元素个数;而集合中拥有元素的个数是表示添加到该集合中的元素个数。Capacity的值始终大于或等于Count的值。

    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不允许排序操作。
    3、Queue和Queue

      Queue成为队列,队列是这样一种数据结构,数据有列表的一端插入,并由列表的另一端移除。就像单行道,只能从一段进,从一端出。Queue类实现了ICollection和IEnumerable接口。

      Queue的一些重要特性。

      1、先进先出

      2、可以添加null值到集合中

      3、允许集合中的元素重复

      4、Queue容量会按需自动添加

      5、Queue的等比因子是当需要更大容量时当前容量要乘以的数字,默认是2.0。

      现在列出Queue一个特性的功能

    成员       类型        说明

    Clear       方法        从Queue中移除所有对象,清空队列。

    Contains     方法        确定某元素是否在Queue中

    Enqueue     方法        将对象添加到Queue的结尾处  入列

    Dequeue     方法        移除并返回位于Queue开始处的对象  出列

    Peek       方法        返回位于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

      Stack称为栈,栈和队列非常相似,只不过队列是先进先出,而栈中的数据添加和移除都在一端进行,遵守栈中的数据则后进先出。Stack类实现了ICollection和IEnumerable接口。

      Stack类的一些重要特性如下:

      1、后进先出。

      2、可以添加null值到集合中。

      3、允许集合中的元素重复。

      4、Stack的容量会按需自动增加。

    列出几个有特点的功能。

    成员      类型        说明

    Clear      方法         从Stack中移除所有对象

    Contains    方法         确定某元素是否在Stack中

    Push      方法         将对象插入Stack的顶部  入栈

    Pop      方法         移除并返回Stack顶部的对象 出栈

    Peek      方法         返回位于Stack顶部的对象,但不移除,注意出栈是移除的。它不移除仅仅返回。

    Count     属性         获取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

      SortedList类实现了IDictionary、ICollection以及IEnumerable接口。SortedList类与HashTable类似,也表示一个键/值对集合,可以通过键和索引对元素进行访问,但不同的是,也是该类的最大作用所在,就是支持基于键的排序。在SortedList中,键和值分别保存在一个数组中,当向Sorted添加一个元素时,SortedList类添加一个元素时,SortedList会首先对key进行排序,然后根据排序结果计算出要插入到集合中的位置索引,再分别将key和value插入到各自数组的指定索引位置。当使用foreach循环集合中的元素时,SortedList会将相同索引位置的key和value放进一个DictionaryEntry类型的对象,然后返回。
      

    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、List
    List是ArrayList的泛型等效版本,两者功能相似。它实现了6个接口,实际上市对应的3对。

    1、IEnumerable和IEnumerable

    2、ICollection和ICollection

    3、IList和IList

      使用List有很多好处。比如类型安全和可以存储引用类型以及值类型的数据,避免了使用ArrayList存储值类型数据时的装箱拆箱操作。以及在存储引用类型时的显示类型转化难操作,有一定的性能优势。

      List类的一些重要特性如下:

      1、可以添加null值到集合中。

      2、允许集合中的元素重复。

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

      在创建List的对象时,没有指定List列表的容量大小,则默认的容量大小是零,但是一旦有数据加入到列表,则列表的容量就会扩展到4;第5个加入时就会扩展到8;第9个加入就扩展到16,如此类推。列表容量总是成倍地增长。扩展时需要重新申请内存,这样会影响效率,如果事先知道元素的数目,或者可能的数目(尽量大的估算),建议使用一个初始化容量来实例化List对象。

      构造方法:

      1、List();  使用默认的初始容量初始化一个空的实例。

      2、List(IEnumerable collection)  创建一个实例,并从指定的集合中复制元素到新实例中。

      3、List(Int32)  使用指定的容量初始化一个空的实例。

      属性              说明

      Capacity             获取或设置该内部数据结构在不调整大小的情况下能够容纳的元素总数。
      Count              获取 List<(Of <(T>)>) 中实际包含的元素数。
      Item               获取或设置指定索引处的元素。

      方法

    Add                将对象添加到 List<(Of <(T>)>) 的结尾处。
    AddRange             将指定集合的元素添加到 List<(Of <(T>)>) 的末尾。
    AsReadOnly            返回当前集合的只读 IList<(Of <(T>)>) 包装。
    BinarySearch           已重载。 使用对分检索算法在已排序的 List<(Of <(T>)>) 或它的一部分中查找特定元素。
    Clear               从 List<(Of <(T>)>) 中移除所有元素。
    Contains             确定某元素是否在 List<(Of <(T>)>) 中。
    ConvertAll<(Of <(TOutput>)>) 将当前 List<(Of <(T>)>) 中的元素转换为另一种类型,并返回包含转换后的元素的列表。
    CopyTo              已重载。 将 List<(Of <(T>)>) 或它的一部分复制到一个数组中。
    Exists              确定 List<(Of <(T>)>) 是否包含与指定谓词所定义的条件相匹配的元素。
    Find               搜索与指定谓词所定义的条件相匹配的元素,并返回整个 List<(Of <(T>)>) 中的第一个匹配元素。
    FindAll              检索与指定谓词定义的条件匹配的所有元素。
    FindIndex             已重载。 搜索与指定谓词所定义的条件相匹配的元素,返回 List<(Of <(T>)>) 或它的一部分中第一个匹配项的从零开始的索引。
    FindLast             搜索与指定谓词所定义的条件相匹配的元素,并返回整个 List<(Of <(T>)>) 中的最后一个匹配元素。
    FindLastIndex          已重载。 搜索与指定谓词所定义的条件相匹配的元素,返回 List<(Of <(T>)>) 或它的一部分中最后一个匹配项的从零开始的索引。
    ForEach             对 List<(Of <(T>)>) 的每个元素执行指定操作。
    GetEnumerator          返回循环访问 List<(Of <(T>)>) 的枚举数。
    GetRange            创建源 List<(Of <(T>)>) 中的元素范围的浅表副本。
    IndexOf             已重载。 返回 List<(Of <(T>)>) 或它的一部分中某个值的第一个匹配项的从零开始的索引。
    Insert              将元素插入 List<(Of <(T>)>) 的指定索引处。
    InsertRange           将集合中的某个元素插入 List<(Of <(T>)>) 的指定索引处。
    LastIndexOf           已重载。 返回 List<(Of <(T>)>) 或它的一部分中某个值的最后一个匹配项的从零开始的索引。
    Remove             从 List<(Of <(T>)>) 中移除特定对象的第一个匹配项。
    RemoveAll            移除与指定的谓词所定义的条件相匹配的所有元素。
    RemoveAt            移除 List<(Of <(T>)>) 的指定索引处的元素。
    RemoveRange          从 List<(Of <(T>)>) 中移除一定范围的元素。
    Reverse             已重载。 将 List<(Of <(T>)>) 或它的一部分中元素的顺序反转。
    Sort               已重载。 对 List<(Of <(T>)>) 或它的一部分中的元素进行排序。
    ToArray             将 List<(Of <(T>)>) 的元素复制到新数组中。
    TrimExcess            将容量设置为 List<(Of <(T>)>) 中的实际元素数目(如果该数目小于某个阈值)。
    TrueForAll            确定是否 List<(Of <(T>)>) 中的每个元素都与指定的谓词所定义的条件相匹配。

    7、HashSet
    类主要是设计用来做高性能集运算的,例如对两个集合求交集、并集、差集等。集合中包含一组不重复出现且无特性顺序的元素。

    HashSet的一些特性如下:

    1、HashSet中的值不能重复且没有顺序。

    2、HashSet的容量会按需自动添加。

    构造方法:

    HashSet() 默认相等比较器创建一个空的新实例。

    HashSet(IEnumerable collection)  把指定集合中的collection中的数据复制到集中

    HashSet(IEqualityComparer comparer)  使用指定的相等比较器创建一个空的新实例

    HashSet(IEnumerable collection,IEqualityComparer comparer)  使用指定的比较器实例化数据,且将指定集合中的元素复制到集合中。

    因为HashSet是专门设计来做集合运算的,因此它提供的方法中有不少是和集合运算相关的。

    以下给出它的一些常用方法介绍

    成员        类型        说明

    Add        方法        将指定的元素添加到集合中

    Clear        方法         清空集合中的所有元素

    Contains     方法         确定某元素是否在HashSet中

    Exists       方法         确定HashSet是否包含于指定条件相匹配的元素

    ExceptWith    方法         从当前HashSet移除指定集合中的所有元素

    IntersectWith   方法        修改当前的HashSet对象,以仅包含该对象和指定集合中存在的元素

    IsProperSubsetOf  方法        确定HashSet对象是否为指定集合的真子集

    IsProperSupersetOf 方法        确定HashSet对象是否为指定集合的真超集

    IsSunsetOf     方法         确定HashSet对象是否为指定集合的子集

    IsSupersetOf    方法         确定HashSet对象是否为指定集合的超集

    Remove      方法         从HashSet对象中移除指定的元素

    RemoveWhere   方法         从HashSet集合中移除与指定谓词所定义的条件相匹配的所有元素

    SetEquals     方法         确定HashSet对象与指定的集合中是否包含相同的元素

    SynmmetricExceptWith  方法     修改当前的HashSet对象,以仅包含该对象或指定集合中存在的元素

    TrimExcess    方法         将HashSet对象的容量设置为它所包含的元素的实际个数,向上舍入为接近的特性与实现的值。

    UnionWith     方法         修改当前的HashSet对象,以包含该对象本身和指定集合中存在的所有元素

    给个简单的例子,写不完的,总之记得HashSet主要的作用是用来进行,交集、并集等运算的就OK了。

  • 相关阅读:
    git分支操作
    redis 和 memcached 有什么区别?redis 的线程模型是什么?为什么 redis 单线程却能支撑高并发?
    缓存如果使用不当会造成什么后果?
    在项目中缓存是如何使用的?
    excel poi3.17导出导入
    Mongodb: Sort operation used more than the maximum 33554432 bytes of RAM
    VMware12上安装CentOS7
    校验文件是否是Excel文件
    读后感——《构建之法》第1.2.3章
    操作系统——实验一
  • 原文地址:https://www.cnblogs.com/polly333/p/4498387.html
Copyright © 2011-2022 走看看