C#里面的不同集合(数组、ArrayList集合、List泛型)

简介: 在内存中连续存储,因此可以快速而容易地从头到尾遍历元素,可以快速地修改元素

数组(Array)


什么是数组?


是一个存储相同类型元素固定大小顺序集合。


有什么作用吗?


一次声明相同类型的数。


有哪些特点?


  • 元素是相同类型
  • 大小固定
  • 元素连续存储
  • 是引用类型(必须分配堆上的内存)


数组有哪些优点?


在内存中连续存储,因此可以快速而容易地从头到尾遍历元素,可以快速地修改元素


数组有哪些缺点呢?


  • 创建时必须要指定数组变量的大小,在两个元素之间添加元素比较困难。
  • 造成数组长度设置过大,内存空间浪费
  • 数组长度过小,溢出


如何创建一个数组?


//第一种方式
 int[] num1 = new int[10];           //长度为10,下标为0-9,int类型
//第二种方式
int[] num2 = new int[] { 1,2,3,4,5};  //此数组就存5个值
//第三种方式
int[] num3 = new int[3] { 1, 2, 3 };  //个数和声明数必须一致。此数组就存3个值,值都清楚
//第四种方式
int[] num4 = { 1, 2, 3, 4, 5 };        //简写法


怎么给数组赋值?


int[] num1 = new int[10];   //长度为10,下标为0-9,int类型
num1[8] = 20;               //给8这个地方赋个值
Console.WriteLine(num1[8]);                                                
Console.ReadKey();


1536560aada3bfecb944bfacb71dfeb6.png


比方,盖一栋楼,一共有10层,有个开房的,它就去找6层房牌号为100的这个房间


如何遍历一个数组循环输出里面的内容


int[] nums = new int[5];              //声明一个数组
for (int i = 0; i < nums.Length; i++)           //赋值
{
    nums[i] = 10;
}
for(int i = 0; i < nums.Length; i++)            //取值
{
    Console.WriteLine(nums[i]);
}
Console.ReadKey();


如何在数组的两个元素之间添加元素?★★★


方法:使用泛型List<T>,先将元素存入List中,最后使用ToArray()转成数组。链接:C#中如何向数组中动态添加元素


第一步、将int数组转成List<int>


int[] num = new int[] { 1, 2, 3, 4 };    //定义一个int类型数组,长度为4
List<int> strList = new List<int>(num);  //将int数组转成泛型List<int>
strList.Add(5);                          //将要添加的元素存入泛型里面(这个方法默认是在结尾添加)
strList.Insert(0, 9);                    //在指定索引处添加值


第二步、List<int>转int数组


int[] numm = strList.ToArray();          //将泛型转成数组
for (int i = 0; i < numm.Length; i++)    //遍历数组元素
{
    Console.WriteLine(numm[i]);          //输出数组的值
}
Console.ReadKey();                       //在控制台输出结果


如何解决数组的这些问题呢?


.NET Framework提供了用于数据存储和检索的专用类,这些类统称集合。这些类提供对堆栈、队列、列表和哈希表的支持。大多数集合类实现相同的接口。来克服这些缺点


集合(ArrayList)


是什么?


动态数组。有序集合


有什么特点?

  • 初始容量为0
  • 不用限定长度
  • 集合可以使用索引在指定的位置添加和移除项目,动态数组会自动调整它的大小
  • 在列表中进行动态内存分配、增加、搜索、排序各项
  • 集合的变量影响全局,始终保证元素的连续性


60c4880c6e29fa7d8d89523eaf36ceb6.png


集合ArrayList相比数组有什么好处吗?(数组和集合的区别有哪些?)

优点

缺点

数组

在内存中连续存储,快速修改元素
  • 创建时长度固定
  • 动态添加元素困难
  • 排序得到冒泡排序

ArrayList集合

  • 不用限定长度
  • 随着元素添加,容量根据需要自动扩充
  • 在列表中进行动态内存分配、增加、搜索、排序各项
ArrayList不是类型安全的


可以将集合看作为“长度可变的,具有很多方法的数组”


有哪些缺点?


ArrayList不管是什么对象都是接受的,因为在它眼里所有元素都是Object,这就使得如果‘arrayAnima.Add(123);’或者‘arrayAnima.Add("HelloWorld");’在编译时都是没有问题的,但在执行时,‘foreach(Animal item in arrayAnima)’需要明确集合中的元素是Anima类型,而123是整型,HelloWorld是字符串型,这就会在运行到此处时报错,显然,这是典型的类型不匹配错误,换句话说,ArrayList不是类型安全的。


ArrayList对于存放值类型的数据,比如int、string型(string是一种拥有值类型特点的特殊引用类型)或者结构struct的数据,用ArrayList就意味着都需要将值类型装箱为Object对象,使用集合元素时,还需要执行拆箱操作,带来很大的性能损耗。

07e957c9206988f633bf1f9915df527d.png


装箱(boxing)、拆箱是什么?

  • 装箱:把值类型“赋值”给引用类型
  • 拆箱:将引用类型“赋值”给值类型


例子:比如整型变量i被“装箱”并赋值给对象o


装箱前,数据类型不必匹配,无法赋值:


2cbd1d6c369126b46d33d1ddc4b75a41.png


装箱后:
int a = 1;
object b = (object) a;   //boxing,分配并构造一个全新的对象
拆箱:
o = 1;
i=(int) o;


如何使用集合?


命名空间:引用 System.Collections


常用的方法


Count:获取长度
arrayList.Clear();  清空集合
arrayList.Contains(1);   判断这个集合中是否包含1这个元素
arrayList.Insert    插入
int num = arrayList.Count;   集合中元素的个数
int num = arrayList.IndexOf(2);  找某一个元素对应的索引
删除数据:Remove() 、RemoveAt() 、Clear()
int[] nums = {1,2,3};
arrayList.InsertRange(4,nums);   往某一个索引位置插入一个数组
arraylist.AddRange(nums)里面可以放数组、集合
arrayList.LastIndexOf() ;   找最后一个元素的索引
arrayList.Remove(1);   移除某一个元素(只移除最开始出现的)
arrayList.RemoveAt(1);移除索引对应的值
arrayList.RemoveRange(3,4)    从指定索引处开始移除,移除多少个,如果超出索引报异常
arrayList arrayList = new ArrayList();
for {int in = 0; int < 100 ; i++}          //循环0-100的数
{
       arrayList.Add(i);                         //循环输出数
}
arrayList.Reverse();    反转
arrayList.Sort()   排序


实例


int[] nums = new int[] { 1, 2, 3, 4, 5, 6 };           //int类型数组
ArrayList arrayList = new ArrayList();                 //实例化一个ArrayList集合对象
arrayList.Add(10);                                     //往集合里面添加一个int类型的值10
arrayList.Add(20);                                     //往集合里面添加一个int类型的值
arrayList.Add("小苏");                                 //往集合里面添加一个string类型的值
arrayList.Add('女');                                   //往集合里面添加一个char类型的值
arrayList.Add(true);                                   //往集合里面添加一个bool类型的值
arrayList.Add(3.15m);                                  //往集合里面添加一个decimal类型的值
arrayList.Add(78.9);                                   //往集合里面添加一个double类型的值
arrayList.Add(nums);                                   //往集合里面添加一个数组
//Person per = new Person("小杨",'男',18);
//arrayList.Add(per);
 //可以写成:
arrayList.Add(new Person("小杨", '男', 18));          //往集合里面添加一个类
            for (int i = 0; i < arrayList.Count; i++)         //遍历这个集合,i++
            {
                if (arrayList[i] is int[])                    //如果集合i里面的元素能够转换为int类型,强转
                {
                    int[] numbers = (int[])arrayList[i];      //就把集合里面的元素赋给这个数组numbers
                    for (int j = 0; j<numbers.Length; j++)    //循环numbers这个数组
                    {
                        Console.WriteLine(numbers[j]);        //把数组里面的元素也循环展示出来,
                    }
                }
                else if (arrayList[i] is Person)              //否则如果集合中的某个元素是Person这个类
                {
                    ((Person) arrayList[i]).Show();           //输出类这个方法
                }
                else                                          //否则
                {
                    Console.WriteLine(arrayList[i]);          //输出集合的结果
                }
            }            


定义集合时添加数组


int[] nums = new int[] { 1, 2, 3, 4, 5, 6 };
ArrayList arrayList = new ArrayList(nums);    //初始集合里面就包括nums数组里的元素
arrayList.Add(1);
arrayList.Add("老牛");
arrayList.AddRange(nums);    //把数组中的所有元素输出出来
arrayList.Add(nums);         //不会输出数组内容
for (int i = 0; i < arrayList.Count ; i++)
{
    Console.WriteLine(arrayList[i]);
}


在数组里面插入元素和修改元素都很困难,所以到了集合,就把那些增删改的方法封装成一个接口,把这些方法放在接口里面,想用随时调用就可以了,克服了数组的缺点。

那如何解决集合的装箱拆箱带来的性能损耗问题?

在C#2.0出版后,推出泛型解决这个问题


泛型(List)


泛型是什么?



??是具有占位符(类型参数)的类、结构、接口和方法,这些占位符是类、结构、接口和方法所存储或使用的一个或多个类型的占位符。


有什么作用呢?


??可以将类型参数用作它所存储的对象的类型的占位符;类型参数作为其字段的类型和其方法的参数类型出现。


有什么特点吗?


  • 就是为了专门处理某种类型
  • 在尖括号中写什么类型,这个集合就变成了什么类型的集合
  • 添加数据、插入数据、索引访问数据都是这个类型的,不用考虑所有的转换问题


泛型和集合的区别


  • arrayList集合:不知道存什么类型,不知道存多少个
  • List:知道存什么类型,不知道存多少个


实例


static void Main(string[] args)
{
    List<int> list = new List<int>();     //实例化int类型
    //随机的往这个List集合中添加十个数字,不能重复,求和,求最大值,求最小值,求平均值
    Random r = new Random();
    int num = 0;
    while (list.Count !=10)
    {
        num = r.Next(1, 100);
        if (!list.Contains (num))
        {
            list.Add(num);
        }
    }
    Console.WriteLine("最大值:{0}",list.Max ());
    Console.WriteLine("最小值:{0}",list.Min ());
    Console.WriteLine("和为:{0}",list .Sum ());
    Console.WriteLine("平均值为:{0}",list.Average ());
    Console.ReadKey();
    List<string> listStr = new List<string>();   //实例化string类型
    listStr.Add("哈哈,小杨又变帅了");
}


那如何选择使用哪一个集合呢?


通常情况下都建议使用泛型集合,因为这样可以获得类型安全的直接优点而不需要从基集合类型派生并实现类型特定的成员。此外,如果集合元素为值类型,泛型集合类型的性能通常优于对应的非泛型集合类型(并优于从非泛型基集合类型派生的类型),因为使用泛型时不必对元素进行装箱。


思维导图


e4bc4531d22d88e4050810d2b0fa06b4.png              

相关文章
|
1月前
|
Java 物联网 C#
C#/.NET/.NET Core学习路线集合,学习不迷路!
C#/.NET/.NET Core学习路线集合,学习不迷路!
|
2月前
|
安全 Java 程序员
深入Java集合框架:解密List的Fail-Fast与Fail-Safe机制
本文介绍了 Java 中 List 的遍历和删除操作,重点讨论了快速失败(fail-fast)和安全失败(fail-safe)机制。通过普通 for 循环、迭代器和 foreach 循环的对比,详细解释了各种方法的优缺点及适用场景,特别是在多线程环境下的表现。最后推荐了适合高并发场景的 fail-safe 容器,如 CopyOnWriteArrayList 和 ConcurrentHashMap。
69 5
|
1月前
|
NoSQL Java Redis
List集合按照由小到大排序或者由大到小排序
List集合按照由小到大排序或者由大到小排序
45 0
|
2月前
|
开发框架 NoSQL MongoDB
C#/.NET/.NET Core开发实战教程集合
C#/.NET/.NET Core开发实战教程集合
|
2月前
|
设计模式 安全 容器
数据结构第一篇【探究List和ArrayList之间的奥秘 】
数据结构第一篇【探究List和ArrayList之间的奥秘 】
29 5
|
2月前
|
存储 分布式计算 NoSQL
大数据-40 Redis 类型集合 string list set sorted hash 指令列表 执行结果 附截图
大数据-40 Redis 类型集合 string list set sorted hash 指令列表 执行结果 附截图
29 3
|
3月前
|
NoSQL Java Redis
List集合按照由小到大排序或者由大到小排序
List集合按照由小到大排序或者由大到小排序
26 3
|
1月前
|
C# 开发者
C# 一分钟浅谈:Code Contracts 与契约编程
【10月更文挑战第26天】本文介绍了 C# 中的 Code Contracts,这是一个强大的工具,用于通过契约编程增强代码的健壮性和可维护性。文章从基本概念入手,详细讲解了前置条件、后置条件和对象不变量的使用方法,并通过具体代码示例进行了说明。同时,文章还探讨了常见的问题和易错点,如忘记启用静态检查、过度依赖契约和性能影响,并提供了相应的解决建议。希望读者能通过本文更好地理解和应用 Code Contracts。
37 3
|
6天前
|
存储 安全 编译器
学懂C#编程:属性(Property)的概念定义及使用详解
通过深入理解和使用C#的属性,可以编写更清晰、简洁和高效的代码,为开发高质量的应用程序奠定基础。
40 12
|
1月前
|
设计模式 C# 图形学
Unity 游戏引擎 C# 编程:一分钟浅谈
本文介绍了在 Unity 游戏开发中使用 C# 的基础知识和常见问题。从 `MonoBehavior` 类的基础用法,到变量和属性的管理,再到空引用异常、资源管理和性能优化等常见问题的解决方法。文章还探讨了单例模式、事件系统和数据持久化等高级话题,旨在帮助开发者避免常见错误,提升游戏开发效率。
52 4