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              

相关文章
|
2月前
|
安全 Java 程序员
深入Java集合框架:解密List的Fail-Fast与Fail-Safe机制
本文介绍了 Java 中 List 的遍历和删除操作,重点讨论了快速失败(fail-fast)和安全失败(fail-safe)机制。通过普通 for 循环、迭代器和 foreach 循环的对比,详细解释了各种方法的优缺点及适用场景,特别是在多线程环境下的表现。最后推荐了适合高并发场景的 fail-safe 容器,如 CopyOnWriteArrayList 和 ConcurrentHashMap。
65 5
|
1月前
|
NoSQL Java Redis
List集合按照由小到大排序或者由大到小排序
List集合按照由小到大排序或者由大到小排序
45 0
|
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
|
3月前
|
安全 程序员 编译器
C#一分钟浅谈:泛型编程基础
在现代软件开发中,泛型编程是一项关键技能,它使开发者能够编写类型安全且可重用的代码。C# 自 2.0 版本起支持泛型编程,本文将从基础概念入手,逐步深入探讨 C# 中的泛型,并通过具体实例帮助理解常见问题及其解决方法。泛型通过类型参数替代具体类型,提高了代码复用性和类型安全性,减少了运行时性能开销。文章详细介绍了如何定义泛型类和方法,并讨论了常见的易错点及解决方案,帮助读者更好地掌握这一技术。
84 11
|
4月前
|
Java
用JAVA架建List集合为树形结构的代码方法
这段代码定义了一个表示树形结构的 `Node` 类和一个用于构建树形结构的 `TreeController`。`Node` 类包含基本属性如 `id`、`pid`、`name` 和 `type`,以及子节点列表 `children`。`TreeController` 包含初始化节点列表并将其转换为树形结构的方法。通过过滤和分组操作实现树形结构的构建。详情可见:[代码示例链接1](http://www.zidongmutanji.com/zsjx/43551.html),[代码效果参考链接2](https://www.257342.com/sitemap/post.html)。
46 5
|
6月前
|
安全 Java
java线程之List集合并发安全问题及解决方案
java线程之List集合并发安全问题及解决方案
1024 1
|
5月前
|
Java API Apache
怎么在在 Java 中对List进行分区
本文介绍了如何将列表拆分为给定大小的子列表。尽管标准Java集合API未直接支持此功能,但Guava和Apache Commons Collections提供了相关API。
|
5月前
|
运维 关系型数据库 Java
PolarDB产品使用问题之使用List或Range分区表时,Java代码是否需要进行改动
PolarDB产品使用合集涵盖了从创建与管理、数据管理、性能优化与诊断、安全与合规到生态与集成、运维与支持等全方位的功能和服务,旨在帮助企业轻松构建高可用、高性能且易于管理的数据库环境,满足不同业务场景的需求。用户可以通过阿里云控制台、API、SDK等方式便捷地使用这些功能,实现数据库的高效运维与持续优化。