ArrayList类
由于在使用时一个数组的长度不能预先知道或者可能在一个程序的生命周期中改变,静态数组并不是很有用。此问题的一种解决方案是在程序中使用一种当超过默认的存储空间时可以动态调整大小的数组。这类数组称为ArrayList,位于.Net类库的System.Collections下。
一个ArrayList对象有一个Capacity属性存储它的大小。这个属性的初始值为16。当一个ArrayList中的元素数达到这个限制时,ArrayList自动添加Capacity属性所表示的16个元素的存储空间。在数组元素的数目可能变大变小的情况下使用ArrayList比使用标准数组的ReDim方法更有效率。
像我们在第一章讨论过的那样,一个ArrayList对象中存储了object类型的对象。如果你需要以强类型方式存储,你需要使用标准的数组或其它的数据结构。
ArrayList类的成员
ArrayList类包含了需要方法与属性来使你可以方便的使用ArrayList。下面是一个最为常用的方法与属性的列表。
Add(): 向ArrayList中添加一个元素。
AddRange(): 向ArrayList的尾部添加一些元素的集合
Capacity: ArrayList默认可以保存的元素的数目
Clear(): 移除ArrayList中的所有元素
Contains(): 判断ArrayList中是否包含一个指定的项
CopyTo(): 拷贝一个ArrayList或者其中的一部分到另一个数组
Count: 返回ArrayList中当前元素的数目
GetEnumerator(): 返回一个枚举器来迭代ArrayList
GetRange(): 取得ArrayList的一个子集作为一个新的ArrayList
IndexOf(): 返回与指定项目第一个匹配的索引
Insert(): 在ArrayList的指定索引处插入一个元素
InsertRange(): 由ArrayList的指定位置处开始插入一个元素的集合
Item: 属性-指定索引处的元素
Remove(): 移除指定项目的第一个匹配
RemoveAt(): 移除指定索引处的元素
Reserve(): 将ArrayList中的元素反序排列
Sort(): 按字母顺序排列ArrayList中的元素
ToArray(): 拷贝ArrayList的元素到一个数组
TrimToSize(): 设置Capacity属性为ArrayList中的实际元素数
使用ArrayList类
ArrayList使用起来不想标准数组。通常,项目是使用Add方法添加到ArrayList中,除非有特殊原因,一个元素需要被添加到一个特殊位置,在这种情况下需要使用Insert方法。在这节中,我们来看一下怎样使用ArrayList中零零总总的方法。
我们首先需要做的是按如下方式声明一个这个类的对象:
ArrayList grades = new ArrayList();
注意在声明中调用了构造函数。如果一个ArrayList不使用构造函数,在后续的程序语句中这个对象不可用。
对象使用Add方法添加一个对象到ArrayList。这个方法接受一个参数 – 一个要添加到ArrayList的对象。同时这个方法也返回一个整型表明元素被添加到的位置,虽然这个值在程序中不常用。下面是一些例子:
grades.Add(100);
grades.Add(84);
int position;
position = grades.Add(77);
Console.WriteLine("The grade 77 was added at position: " + position);
ArrayList中的对象可以使用一个foreach循环来显示。ArrayList有一个内置的枚举器管理ArrayList中所有对象的迭代,一次一个。下面的代码片段展示了怎样在ArrayList中使用一个foreach循环。
int total = 0;
double average = 0.0;
foreach (Object grade in grades)
total += (int)grade;
average = total / grades.Count;
Console.WriteLine("The average grade is: " + average);
如果你要在ArrayList的指定位置添加一个元素,你可以使用Insert方法。这个方法接受两个参数:要插入元素的位置,及要插入的元素。下面的代码片段在指定位置插入两个分数,以保持ArrayList的对象的顺序:
grades.Insert(1, 99);
grades.Insert(3, 80);
你可以通过调用Capacity属性来查看一个ArrayList当前的容量,通过Count属性来查看一个ArrayList中当前的元素数目:
Console.WriteLine("The current capacity of grades is: " + grades.Capacity);
Console.WriteLine("The number of grades in grades is: " + grades.Count);
由数组中移除项有几种方式。如果你知道你要移除的项,但是不知道其所在的位置,你可以使用Remove方法。这个方法仅接受一个参数 – 要由ArrayList移除的对象。如果对象存在于ArrayList中,它将被移除。如果对象不再数组当中,将不会进行任何处理。当类似Remove的方法被调用时,其通常被放在一个If-Then语句内来调用,并使用方法(如Contains方法)验证这个对象是否存在于ArrayList。下面是这个过程的示例代码段:
if (grades.Contains(54))
grades.Remove(54);
else
Console.Write("Object not in ArrayList.");
如果你知道你要移除的对象的索引,你可以使用RemoveAt方法。这个方法接受一个参数-你要移除的对象的索引。唯一会引起的异常时 当你传给方法一个无效的索引。方法工作方式如下:
grades.RemoveAt(2);
通过调用ArrayList的IndexOf方法你可以确定一个对象的位置。这个方法接受一个参数 – 待查找的对象,并返回对象在ArrayList中的位置。如果对象不在ArrayList中,该方法返回-1。一下代码段展示了结合使用IndexOf方法与RemoveAt方法:
int pos;
pos = grades.IndexOf(70);
grades.RemoveAt(pos);
除了添加单个对象到ArrayList外,你也可以添加一个范围的对象。这些对象须是存储于一个实现ICollection接口的类型的对象当中。这意味着对象可以是存储于一个数组,一个集合甚至是另一个ArrayList当中。
有两种不同的方法可以添加一个范围内的对象到ArrayList,分别是AddRange方法与InsertRange方法。AddRange方法添加一个范围的对象到ArrayList的尾部,InsertRange方法添加一个范围的对象到ArrayList中的指定位置。
下面的程序展示了这两个方法的使用:
using System;
using System.Collections;
class class1 {
static void Main()
{
ArrayList names = new ArrayList();
names.Add("Mike");
names.Add("Beata");
names.Add("Raymond");
names.Add("Bernica");
names.Add("Jennifer");
Console.WriteLine("The original list of names: ");
foreach (Object name in names)
Console.WriteLine(name);
Console.WriteLine();
string[] newNames = new string[] { "David", "Michael" };
ArrayList moreNames = new ArrayList();
moreNames.Add("Terrill");
moreNames.Add("Donnie");
moreNames.Add("Mayo");
moreNames.Add("Clayton");
moreNames.Add("Alisa");
names.InsertRange(0, newNames);
names.AddRange(moreNames);
Console.WriteLine("The new list of names: ");
foreach (Object name in names)
Console.WriteLine(name);
}
}
这段程序的输出如下:
David Michael Mike Bernica Beata Raymond Jennifer Terrill Donnie Mayo Clayton Alisa
由于指定的索引为0,前两个名字被添加到ArrayList的起始位置,由于AddRange方法的使用后面的名字被添加到尾部。
另外两个程序员认为有用的方法是ToArray方法与GetRange方法。GetRange方法返回一个ArrayList中指定范围的对象到另一个ArrayList。ToArray方法拷贝ArrayList中所有元素到一个数组。首先我们看一下GetRange方法。
GetRange方法接受两个参数:起始索引及要由ArrayList中检索的元素的数目。GetRange方法是非破坏性的,即它仅仅是由原始ArrayList拷贝对象到新的ArrayList。下面例子展示了这是方法的作用,它使用了前文的程序:
ArrayList someNames = new ArrayList();
someNames = names.GetRange(2, 4);
Console.WriteLine("someNames sub-ArrayList: ");
foreach (Object name in someNames)
Console.WriteLine(name);
程序片段的输出为:
Mike Bernica Beata Raymond
ToArray方法是你可以轻松的将ArrayList中的内容移动到一个标准数组中。你将使用ToArray方法的主要原因是使用数组可以获得更快的访问速度。
ToArray方法不接受参数,并将ArrayList中的元素返回到一个数组中。下面的例子展示了这个方法的使用:
Object[] arrNames;
arrNames = names.ToArray();
Console.WriteLine("Names from an array: ");
for (int i = 0; i <= arrNames.GetUpperBound(0); i++)
Console.WriteLine(arrNames[i]);
代码段的最后一部分证明了ArrayList中的元素已经真实的被存储在arrNames的数组中。
摘要
数组是计算机程序设计中最常用的数据结构。几乎所有的计算机语言内建对各类形式数组的支持。
对许多程序,数组是最易实现的数据结构且最高效。当你需要直接访问你数据集中一个位于后部的元素时,数组非常有用。
.NET Framework引入了一种称为ArrayList的新类型的数组。ArrayList有很多数组的特点,但是更为强大,因为当达到最大容量时它们可以调整自身的大小。ArrayList也有一些实用的方法,如执行插入,声明与查找。由于C#中不允许像在VB.NET中那样动态调整一个数组的大小,所以当你处理一个无法提前预知项目的数目的存储时ArrayList就是一种很有用的数据结构。
联系
1. 设计并实现一个类,使教师可以跟踪一门课的分数。其中包括计算平均成绩,最高分,最低分的方法。写一个程序来测试你类的实现。
2. 修改联系1中的类,使其可以记录多个课程的成绩。写一个程序来测试你的实现。
3. 使用ArrayList重写联系1.编写一个程序来测试你的实现,并使用Timing类来比较其与联系1的数组实现性能。
4. 设计并实现一个类,使用数组来模拟ArrayList类的行为。尽可能多的实现ArrayList中的方法。编写一个程序来测试你的类。