(教学思路 C#集合一)集合的概述、动态数组ArrayList

 这一节我们来学习集合,什么是集合呢? 集合就如同数组,用来存储和管理一组特定类型的数据对象,除了基本的数据处理功能,集合直接提供了各种数据结构及算法的实现,如队列、链表、排序等,可以让你轻易地完成复杂的数据操作。在使用数组和集合时要先加入system.collections命名空间,它提供了支持各种类型集合的接口及类。集合本身上也是一种类型,基本上可以将其作为用来存储一组数据对象的容器,由于c#面向对象的特性,管理数据对象的集合同样被实现成为对象,而存储在集合中的数据对象则被称为集合元素。这里提到了接口这个概念,它也是面向对象编程进化的重要标准,我们在这里不做过多的讲解,先注重学习集合中的对象及其使用就可以了,下面我们来学习第一种集合:

         动态数组ArrayList.ArrayList类提供了继承了IList接口。什么是继承呢?这也是面向对象语言的重要特点之一,现在你们先把它理解为,如果一个对象继承了类或接口,那么它也具有了这个类和接口中的方法、属性,可以用这些继承的方法和属性来做相应的操作,比如:数组增加元素没有Add()方法,但是动态数组ArrayList继承了一个增加元素有Add()方法的接口,那么当它要增加元素的时候,不仅可以用索引,也可以用继承下来的Add()方法了。随着学习的深入,我会给大家再具体讲解继承的概念和使用继承的好处。那么下面让我们来看看动态数组所继承的这个接口IList它有什么特性呢?

     Ilist接口:定义了利用索引访问集合对象的方法,还继承了ICollection和IEnumerable接口,除实现了接口原有的方法成员外,其本身也定义多个专门的方法成员,例如新增、移除、在指定位置插入元素或是返回特定元素在集合中所在的位置索引,这些方法主要为集合对象提供类似数组的元素访问功能。
     ILsit接口成员:add、insert、RemoveAt、Remove、contains、Clear、indexof方法,它最大的特色在于提供类似数组索引的访问机制。

    ArrayList对象是较为复杂的数组。我们可以将它看为扩充了功能的数组,但ArrayList并不等同于数组,与数组相比,它以下功能和区别是:

1.  数组的容量是固定的,但ArrayList的容量可以根据需要自动扩充。当我们修改了ArrayList的容量时,则可以自动进行内存重新分配和元素复制,比如往1号索引位插入n个元素,插入后,元素的索引依次向后n个位置排列,它是动态版本的数组类型。

2.ArrayList提供添加、插入或移除某一范围元素的方法。但是在数组中,只能一次获取或设置一个元素的值,如利用索引赋值。

3.ArrayList只有一维,而数组可以是多维。
       如何声明一个动态数组呢?

ArrayList  AL=new ArrayList( Capacity );//初始容量capacity也是可以不写的 

原因就是即使不在初识化确定容量,容量不够的时候,会自动的按倍数作扩充。

接下来我们来看一下动态数组的常用属性

Capacity     获取或设置ArrayList可包含的元素数。

Count        获取ArrayList中实际包含的元素数。

IsReadOnly 获取一个值,该值表示ArrayList是否为只读。

Item           获取或设置指定索引处的元素。  

 动态数组的常用方法  

增加元素-ArrayList.Add(value);利用Add方法增加集合元素值

我们也可以索引增加元素ArrayList[Index]=value;
插入元素-ArrayList.Insert(Index,value);将元素的值value,插入到第Index位置。
删除元素-ArrayList.Clear();  全部删除集合中的元素

             ArrayList.Remove(value);按照集合元素值删除元素

             ArrayList.RemoveAt(Index);按照集合的元素索引删除元素
缩减容量-ArrayList.TrimToSize();将集合的容量减少到实际元素个数的大小

               在执行删除操作后,要养成良好的缩减容量的习惯,节省内存空间,提高性能。
查找元素-除了按数组的索引查找外,还可以用ArrayList.Contains(value);按照元素值查找集合,如果包含便返回True,不包含时返回False。

   下面的例子我会给你们分部的演示出以上方法及属性,运行结果我会用图片的形式显示出来,帮助你们理解动态数组是使用。

ArrayList AL = new ArrayList();

AL.Add("Hello");

AL.Add(" World");

Console.WriteLine("给数组添加元素");

foreach (Object obj in AL)

{ Console.Write(obj); }

Console.WriteLine();

Console.WriteLine("个数:" + AL.Count);

Console.WriteLine("容量: " + AL.Capacity);

AL.Insert(1, " c#");

Console.Write("在索引值为1的地方插入 ");

 foreach (Object obj in AL)

{Console.Write(obj); }

 Console.WriteLine();

 Console.WriteLine("个数:" + AL.Count);

 Console.WriteLine("容量: "+AL.Capacity);

 

AL.Add("");//给集合添加“。”,查看集合的容量

Console.WriteLine("容量。: " + AL.Capacity);

 AL.Add("---");//给集合添加“---”,查看当集合的容量不够时,倍数变化

Console.WriteLine("容量---: " + AL.Capacity);

Console.WriteLine("3号索引的"+AL[3]);//用索引方式获取集合元素值

Console.WriteLine("数组中是否包含?"+AL.Contains ("?")); //利用contains方法,查找集合中是否包含“?”

Console.WriteLine("经过之前操作后的数组元素:");

foreach (Object obj in AL)

{ Console.Write(obj); }

Console.WriteLine();

Console.WriteLine("个数:" + AL.Count);

Console.WriteLine("容量: " + AL.Capacity);

AL.Remove("");//移除集合中的“。”元素

AL.Remove("?");//移除集合中的“?”,但是因为没有“?”,所以此行代码不会对集合进行操作。

Console.WriteLine("没有?个数只减少1个容量不变");

foreach (Object obj in AL)

{ Console.Write(obj); }

Console.WriteLine();

Console.WriteLine("个数:" + AL.Count);

Console.WriteLine("容量: " + AL.Capacity);

AL.RemoveAt(3);//移除3号索引的元素

Console.WriteLine("移除3号索引位的元素:");

foreach (Object obj in AL)

{ Console.Write(obj); }

Console.WriteLine();

Console.WriteLine("个数:" + AL.Count);

Console.WriteLine("容量: " + AL.Capacity);

AL.TrimToSize();               //缩减容量

 Console.WriteLine("实际容量: " + AL.Capacity);

AL.Clear();

Console.WriteLine("清除全部元素后:");

Console.WriteLine("个数:" + AL.Count);

Console.WriteLine("容量: " + AL.Capacity);

 

 AL.TrimToSize();               //缩减容量

 Console.WriteLine(“再次缩减实际容量: " + AL.Capacity);

回到了ArrayList最初的容量。

 

      通过以上的例子你们应该已经理解集合的方法,我们再来总结一下集合ArrayList相比数组有什么好处?主要是它可以根据使用大小按需动态增加,不用受事先设置大小的控制,还有就是可以随意的添加、插入或移除某一范围元素,比数组要方便。但是它也有不足ArrayList 不管对象是什么类型都会添加到集合j中,在编译时都是没有问题的,但是在遍历的时候,为防止集合中元素的类型不一致,所以最好使用object类型来接收遍历j的元素,如foreach(object i in j)这样就能减少错误,可能同学们会想,用object类型我们记住了,怎么就成弊端的呢?

 

这里我们就要学到另一个知识点,就是装箱和拆箱。所谓装箱就是把值类型打包成object引用类型的一个实例中,也就是说在进行装箱的时候,必须分配并构造一个全新的对象。而拆箱就是指从对象中提取值类型,将object类型强制转换为原类型。

  比如: ArrayList j=new ArrayList();

           j.Add(123);

           j.Add("123");

          在添加时,ArrayList是会隐式的将整形的123 进行如下装箱操作:  int i=123;  object o=(object)i;也就是说存进j的元素都将变成object类型

          而在使用这个整形的123时,ArrayList又会进行如下的拆箱操作:   o=123;      i=(int)o;  也就是将o再强制转换成原来的类型表现出去

  想想这将是很大的性能消耗,需要进行大量的计算,至于怎么记住装箱拆箱,我们就把这个过程想象成现实生活中,你买了很多中水果(元素),为了方便搬运,我们把他们都放到一个大盒子(集合对象)里,但是因为有榴莲,我们又得把榴莲(值类型元素)单独包装好(装箱过程)再放到盒子里,到了家后,我们要打开盒子取出水果,在拿到榴莲时,要想见到真正的榴莲,我们就的把包装去掉(拆箱),我们马上就闻到了榴莲那独有的味道了(变回原类型)。哎!这个过程多麻烦呀!分了这么多步,在C#2.0出来后,就推出了新的技术来解决这个问题,那就是泛型,以后的章节我会讲解这个新特性。    

 

 

下面我们来讲一下ArrayList向数组的转换。

     

ArrayList.ToArray() // 转换成object类型数组
ArrayList.ToArray(Type ) // 转换成Type类型数组
                             ArrayList arl = new ArrayList(3);
            string[] ar = new string[3];
            arl.Add("W");
            arl.Add("h");
            arl.Add("y");
            //限定string类型,将arl强制转换string类型数组
            ar = (string[])arl.ToArray(typeof(string));
            foreach (string a in ar)
            {
                Console.Write(a+"   ");
            }
结果输出是 W h y  动态数组的内容就讲解到这,留一道上机作业 :设计一个程序,创建ArrayList数组对象,存储利用Random类产生的10个随机数值,并在排序之后输出到控制台。          

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值