VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > 编程开发 > C#编程 >
  • C#教程之C# 基础知识系列- 3 集合数组

本站最新发布   C#从入门到精通
试听地址  
https://www.xin3721.com/eschool/CSharpxin3721/

简单的介绍一下集合,通俗来讲就是用来保管多个数据的方案。比如说我们是一个公司的仓库管理,公司有一堆货物需要管理,有同类的,有不同类的,总而言之就是很多、很乱。我们对照集合的概念对仓库进行管理的话,那么 数组就是将一堆货整整齐齐的码在仓库的某个地方,普通列表也是如此;Set就是在仓库里有这么一个货架,每种货品只能放一个,一旦某种货品超过一个了货架就塌了;Dictionary字典呢,在一个货架上随机摆放,然后再找一个本子把每个货品存放的位置记录下来。

1. 主要集合

C#/.NET Framework 提供了很多很有意思的集合类,数组、列表、链表、Set、字典等一系列的类。其中数组是语言的一部分,个人认为严格意义上不属于集合类这一部分。C#开发中常用的集合有数组、 List类、Set接口、Dictionary类、Queue类、LinkedList类等,其他的出镜率不高。
与其他(java)语言不同的一点是,C#的List是类,而不是接口,接口是IList,但这个接口意义不大,在使用IList的时候更多的倾向于使用IEnumerable,这主要是因为IEnumerable 有 Linq的支持再者两者的方法基本一致,能用IList的地方基本都可以用IEnumerable

1.1 Array 数组

数组,集合的基础部分,主要特点是一经初始化就无法再次对数组本身进行增删元素。C#虽然添加了一些修改数组的扩展方法,但基本都会返回新的数组对象。

1.1.1 初始化

数组的初始化需要指定大小,可以显示指定或者隐式的指定。

// 显示指定类型与大小,具体的元素后续赋值
string[] strArr = new string[10]; 
//指定类型同时给元素赋值,具体大小由编译器自动推断
string[] strArr1 = new string[]{"1","2","3","4","5","6","7","8","9","10"};
// 类型和大小都由编译器进行推断
string[] strArr2 = new []{"1","2","3","4","5","6","7","8","9","10"}; 

1.1.2 常用方法

  1. 访问和赋值
    数组可以通过下标访问数组中的元素,下标从0开始,表示0位。代码如下:
string item0 = strArr[0]; //取出 "1"
string item2 = strArr[2]; // 取出 "3"
strArr[0] = "3"; // strArr = {"3","2","3","4","5","6","7","8","9","10"}
  1. 获取长度
int length = strArr.Length;// 获取一个整型的长度
//获取一个长整型的长度,对于一个非常大的数组且长度可能会超过int的最大值
long longLength = strArr.LongLength;
  1. 循环迭代
// 普通for 循环
for(int i = 0;i < strArr.Length;i++)
{
	string it = strArr[i];
}
// foreach 循环
foreach(string it in strArr)
{
	// 依次循环,不需要下标,操作更快一点
}

1.1.3 不常用但有用的方法

  1. CopyTo 复制到

    public void CopyTo(Array array, int index);
    public void CopyTo(Array array, long index);
    

    参数说明: array 需要复制到的数组,index 目标数组的起始下标

    方法说明:将 源数组的元素依次复制到 array从index下标开始的位置

    string[] strArr1 = new string[]{"1","2","3","4","5","6","7","8","9","10"};
    string[] strArr3 = new string[10];
    strArr1.CopyTo(strArr3, 0); //strArr3 = {"1","2","3","4",'5","6","7","8","9","10"}
    
    

    值得注意的是strArr3的长度不能 小于 index + strArr1.Length

  2. Sort 排序

    这个方法不是数组对象的方法,而是 Array 提供的一个静态方法。

    int[] arr1 = new[] {1, 9, 28, 5, 3, 6, 0, 12, 44, 98, 4, 2, 13, 18, 81, 92};
    Array.Sort(arr1);//0,1,2,3,4,5,6,9,12,13,18,28,44,81,92,98
    

    值得注意的是,该方法是直接对数组进行操作,所以不会返回新的数组。

  3. ToList 转成 List

顾名思义,将Array对象转成List对象。这里需要额外注意的是,转换成的List是不可改变长度的
4. Clone() 获得一个浅拷贝的数组对象

获取该对象的一个浅拷贝数组对象。

至于其他的Array类和Array对象 还有很多有意思的方法,但是平时开发的时候使用的频率比较低。这里就不一一介绍了,以后需要会介绍一下的。

1.2 List 列表

List列表为一个泛型类,泛型表示<T>,其中T表示列表中存放的元素类型,T代表C#中可实例化的类型。关于泛型的具体描述以后介绍,现在回过头来继续介绍列表。列表内部持有一个数组对象,列表有两个私有变量:一个是列表容量,即内部数组的大小;另一个是存放的元素数量,通过Count获取。
List列表通过元素数量实现了AddRemove 的操作,列表对象操作引发元素数量变动时都会导致对容量的重新计算,如果现有容量不满足后续操作需要的话,将会对现有数组进行扩充。

1.2.1 初始化

List<string> list = new List<string>();// 初始化一个空的列表
List<string> list1 = new List<string>{"12", "2"};//初始化一个包含两个元素的列表
list1 = new List<string>(100);//初始化一个空的列表,并指定list的初始容量为100
list = new List<string>(list1);// 使用一个List/Array 初始化一个列表

1.2.2 常用方法

  1. Count 或LongCount获取元素的数量

    Count 表示获取一个int类型的的数量值,LongCount表示获取一个long类型的数量值。通常情况下两者返回的结果是一致的,但是如果列表中元素的数量超过了int允许的最大返回直接使用 Count获取将会出现数据溢出的问题,这时候就需要LongCount了。

  2. 访问元素/修改元素

    C#的列表操作单个元素很简单 ,与数组的操作方式完全一样。

    string str = list1[0];//获取 list1 的第一个元素,即下标为0的元素
    

list1[2] = "233"; // 将 list1 的第三个元素设置为“233” ,即下标为2 的元素,这里假设list1有至少三个元素
```
需要注意的地方是,如果给定的下标超过了List对象的索引值范围会报ArgumentOutOfRangeException。判断方法就是 下标>= Count,如果满足就会越界。
3. AddAddRange 添加到列表最后

将元素添加到List的末尾,`Add`添加一个,`AddRange`添加一组,支持数组、列表。


```c#
List<string> list = new List<string>();// 初始化一个空的列表
list.Add("12");//list = {"12"}
List<string> list1 = new List<string>{"14", "2"};
list.AddRange(list1);// list = {"12","14","2"}
```
  1. Insert(int index, T item)InsertRange(int index,IEnumerable<T> items) 插入

    • Insert(int index,T item) 在 index 下标处插入一个元素,该下标以及该下标以后的元素依次后移
    • InsertRange(int index,IEnumerable<T> items) 在index下标处插入一组元素,该下标以及之后的元素依次后移

    示例:

    List<int> arr1 = new List<int>{1, 9, 28, 5, 3, 6, 0, 12, 44, 98, 4, 2, 13, 18, 81, 92};
    arr1.Insert(3,37);// arr1 = 1,9,28,37,5,3,6,0,12,44,98,4,2,13,18,81,92 下标为3的元素变成了37,之后的元素依次后移了
    
    List<int> arr1 = new List<int>{1, 9, 28, 5, 3, 6, 0, 12, 44, 98, 4, 2, 13, 18, 81, 92};
    List<int> arr2 = new List<int>{2,3,4,5};
    arr1.InsertRange(2,arr2);//arr1=  1,9,2,3,4,5,28,5,3,6,0,12,44,98,4,2,13,18,81,92 可以明显发现下标为2的元素发生了变化
    
  2. Contains(T item) 是否包含
    返回一个Boolean类型的结果,如果包含则返回true,如果不包含则返回false

    List<int> arr2 = new List<int>{2,3,4,5};
    arr2.Contains(8);//false
    arr2.Contains(3);//true
    
  3. Remove(T item) 删除指定元素

    List<int> arr2 = new List<int>{2,3,4,5};
    arr2.Remove(3);// arr2 = 2,4,5
    arr2.Remove(6);//arr2 = 2,4,5
    

    值得注意的是,如果删除一个不存在的元素时,不会报错,列表也不会发生任何改变。

  4. RemoveAt(int index) 删除位于下标的元素

    List<int> arr2 = new List<int>{2,3,4,5};
    arr2.RemoveAt(1);//arr2 = 2,4,5
    

    如果移除的下标超过了列表的最后一个元素的下标将会抛出异常

  5. RemoveRane(IEnumerable<T> items) 删除一组元素

    Remove(T item)一致,如果要删除的元素不在列表中,则列表元素不会发生变化。

    List<int> arr1 = new List<int>{1, 9, 28, 5, 3, 6, 0, 12, 44, 98, 4, 2, 13, 18, 81, 92};
    List<int> arr2 = new List<int>{2,3,4,5};
    arr1.RemoveRange(arr2);
    
  6. GetRange(int index,int count)

    从列表中获取一个子列表,从index开始,获取count个元素,如果源列表中从index开始剩余的元素不足count个将会报错。

1.2.3 不常用但有用的方法

  1. Clear()删除所有元素

    将列表清空,调用方法之后,列表中将不包含任何元素

  2. Reverse() 调转顺序

    将列表按照从尾到头的顺序进行排列

  3. IndexOf(T item) 查找下标

    查找元素在列表中的下标,如果没找到元素,则返回-1

  4. Sort()排序

    对列表进行排序,调用方法后,会按照默认排序方法返回一个排序结果

1.3 Set 集合

C#没有为Set单独设置类,一方面是因为Set出镜率不高,另一方面也因为Set本身的机制所致。Set集合不能包含重复元素,如果尝试存入重复元素集合元素将不会发生任何变化。
Set集合中元素的顺序与存放顺序不一定相同。因为Set集合中存放对于使用者而言是乱序存放的。
我们常用的Set集合有 HashSet<T>SortSet<T>,其他的Set相关类则属于更加少见。至少在我5年多的开发经历中没有用过。

1.3.1 HashSet<T> 和SortSet<T>

  • HashSet 俗称 哈希集合或者哈希Set,内部使用Hash值作为元素的唯一性验证,即调用对象的HashCode()方法作为Hash值的来源。
  • SortSet 顾名思义,排序集合,它每次在插入的时候都会对元素进行一次排序

1.3.2 共同点

  1. 初始化

    两者相同的地方就是 都有以下几种初始化方法

    Set<T> set = new HashSet<T>();// = new SortSet<T>(); 初始化一个空的集合
    //使用一个集合对象初始化
    Set<T> set1 = new HashSet<T>(IEnumerable<T> items);// = new SortSet<T>(IEnumerable<T> items); 
    Set<T> set2 = new HashSet<T>(){T t1, T t2, T t3};// 与上一种一样
    
  2. 添加元素

    set1.Add(item);// 集合只支持添加单个元素,但是可以通过集合运算的方式增加多个元素
    
  3. 移除元素

    set1.Remove(item);//删除集合中与item判断相等的元素
    
  4. 访问元素

    需要注意的地方是,C#对Set没有支持下标访问方式获取Set里的元素,这是因为索引位置对于集合来说意义不大,没有操作意义。

    foreach (var item in set1)
    {
    	// 操作
    }
    

    Set 只能通过遍历访问元素,不能通过Get或者下标操作访问元素。关于foreach循环会在下一篇《C#基础知识系列》里进行介绍。

  5. 集合运算

    file

    1. UnionWith 并

      SortedSet<int> set = new SortedSet<int>{1,0,29,38,33,48,17};
      set.UnionWith(new []{5,57,8,4,3,1,0,33}); // set = 0,1,3,4,5,8,17,29,33,38,48,57
      

      通过传入一个集合对象,将该集合设置为两个集合的并集,也就是说取上图 A,B,C 三个区域的和

    2. ExceptWith 差

      SortedSet<int> set = new SortedSet<int>{1,0,29,38,33,48,17};
      set.ExceptWith(new []{5,57,8,4,3,1,0,33}); // set =17,29,38,48
      

      传入一个集合,从set中去掉同属于两个集合的元素,保留只存在于set的元素,也就是取上图中的A部分元素

    3. IntersectWith 交

      SortedSet<int> set = new SortedSet<int>{1,0,29,38,33,48,17};
      set.ExceptWith(new []{5,57,8,4,3,1,0,33}); // set =0,1,33
      

      传入一个集合,保留set与传入集合里相同的元素,也就是说取的是上图中的B部分

    4. SymmetricExceptWith 余集

      SortedSet<int> set = new SortedSet<int>{1,0,29,38,33,48,17};
      set.SymmetricExceptWith(new []{5,57,8,4,3,1,0,33});//set= 3,4,5,8,17,29,38,48,57
      

      传入一个集合,保留set与传入集合两个集合中不同的元素,也就是取上图的A+C这两部分。

  6. Contains 包含

    判断集合中是否包含目标元素,返回true/false

    SortedSet<int> set = new SortedSet<int>{1,0,29,38,33,48,17};
    set.Contains(1);// true
    

1.3.3 不同点

  1. 初始化
    • HashSet<T> 支持传入一个自定义的相等比较器,该比较器需要返回一个 bool值;可以指定起始容量
    • SortSet<T> 支持传入一个自定义的大小比较器,该比较器返回一个int值;不能指定起始容量
  2. 其他
    Comparer 属性:SortSet 可以获取大小比较器;HashSet 获取一个相等比较器

1.4 Dictionary 字典

Dictionary 字典,正如它的名称一样,Dictionary 需要指定两个类型,一个作为索引键,一个作为数据值。就像字典一样,每一个词条内容都只有一个字词索引,但可以出现同义词一样。当然,作为我博大精深的中文会出现同字不同音的词组,但是一旦把音、字组合起来作为索引,那还是只会出现一个词条。
所以 Dictionary的使用方式也跟字典一样,通过索引访问和操作数据。

1.4.1 初始化

Dictionary的初始化有如下几个方法:

Dictionary<string, int> dict = new Dictionary<string, int>();// 键是字符串,值是int类型
Dictionary<string,int> dict1 = new Dictionary<string, int>(10);// 指定初始容量是10
Dictionary<string,int> dict2 = new Dictionary<string, int>()
{
	{"1",1},
	{"2",2}
};// 在大括号标记中 通过 {key,value}的写法创建一个 字典对象,并包含这些键值对

// 传入一个字典对象,以传入的对象为基础创建一个字典
Dictionary<string,int> dict3 = new Dictionary<string, int>(dict2);

      



  
相关教程