计算机天生擅长于处理大量数据。在你作为一个开发者的每日工作中,你将发现以一种有序的方式去存储数据是必须的。.NET Framework通过支持一系列的集合去存储你的数据。对于每种集合任务,.NET Framework都提供了解决方案。
本课后,你将能够:
■ 创建一个集合。
■ 从一个集合中增加或删除数据项。
■ 在一个集合中去迭代数据项。
集合种类
The .NET Framework的System.Collections namespace 支持几种集合类型。这些类型是一些类,这些类支持以一定顺序去收集信息。你的挑战将是去辨别正确的集合在具体的实例中。表4—1显示在System.Collections命名空间中使用最频繁的集合,以及它们是用来干什么的。
表 4-1 集合类型
名称 描述
ArrayList 一个简单的可改变大小的基于索引的对象集合。
SortedList 对象的键/值对的分类集合。
Queue 一个先进后出的对象集合。
Stack 一个后进先出的对象集合。
Hashtable 一个对象的键/值对的集合,它允许通过键或所有获取集合项。
BitArray 一个布尔类型的压缩集合
StringCollection 一个简单可变大小的字符串集合。
StringDictionary 一个关于字符串的键/值对的集合,它允许通过键或索引获取。
所有的这些集合在不同的情况下被使用。这一章的第一课将会解释这些集合,以及什么时候去使用哪个集合。ArrayList 是所有集合中最基本的集合。
添加和删除集合项
ArrayList类是能够容纳任何类型对象的一个简单,无序的容器。从这个集合类中添加和删除数据项非常地直接。ArrayList提供两种方法去向集合中添加集合项:
方法Add和方法AddRange.
Add 方法允许你向集合添加一个对象。你能使用Add 方法存储.NET中的任何类型的对象. 以下是不同的类型加入ArrayList 的代码:
ArrayList coll = new ArrayList();
// Add individual items to the collection
string s = "Hello";
coll.Add(s);
coll.Add("hi");
coll.Add(50);
coll.Add(new object());
注意你能够加入对象,对象可能是作为变量存在或Add方法调用时创建(如coll.Add("hi");
)
你甚至可以加入值类型。值类型能够被存入到集合,但是首先它们需要被一个对象引用所封装,一个被称为boxing的过程。
除了支持Add 方法, ArrayList 还支持 AddRange方法去加一个范围内的集合项,通常是一个数组或其它的集合。如以下代码:
string[] anArray =
new string[] { "more", "or", "less" };
coll.AddRange(anArray);
object[] anotherArray =
new object[] { new object(), new ArrayList() };
coll.AddRange(anotherArray);
AddRange 方法支持一个范围内的集合,但这个集合必须要实现ICollection 接口 (包括所有的数组, ArrayList 对象, 以及这章讨论的大部分集合). Add和AddRange方法会把集合项加入集合的尾部。因为ArrayList 是动态集合,它们也支持向特定的位置插入集合项。为了完成这个功能,ArrayList也支持Insert和InsertRange方法,如下:
coll.Insert(3, "Hey All");
string[] moreStrings =
new string[] { "goodnight", "see ya" };
coll.InsertRange(4, moreStrings);
除了Insert 和 Add 方法, 你也能使用索引去设置一个特别的对象,如:
Coll[3] = "Hey All";
最后,ArrayList支持从集合中删除集合项。有三个删除方法:Remove, RemoveAt, 和 RemoveRange. Remove 方法将会从集合中删除一个特定的对象。如果Remove 方法找不到要删除的项不会有任何只是。换句话说,如果数据项在集合中找不到,这个方法也不会报异常。如下:
coll.Add("Hello");
coll.Remove("Hello");
相反地,RemoveAt方法在集合中删除一个具体的数据项时,如何不存在会报异常。
另外, RemoveRange 方法支持删除一次性删除一个范围内的集合项。如下:
// Removes first item in ArrayList
coll.RemoveAt(0);
// Removes first four items in ArrayList
coll.RemoveRange(0, 4);
ArrayList 类也支持其它的方法,这些方法被用于从集合中添加或删除对象:
■ Clear 方法被用于清空集合内的所有项。
■ IndexOf 方法用于确定在集合中特定集合项的索引号。
■ Contains 方法被用于测试在集合中是否存在一个特定的数据项
通过使用这些方法,你能对集合中的项进行更复杂的添加和删除操作:
string myString = "My String";
if (coll.Contains(myString))
{
int index = coll.IndexOf(myString);
coll.RemoveAt(index);
}
else
{
coll.Clear();
}
迭代数据项
ArrayList (以及这章提到的大部分的集合) 支持几种方法去迭代集合项。
ArrayList支持一个数字索引,它允许你去写简单的代码,如下,
for (int x = 0; x < coll.Count; ++x)
{
Console.WriteLine(coll[x]);
}
通过使用ArrayList的Count属性和索引器,你能简单的遍历这个集合。ArrayList也支持IEnumerable接口去实现用枚举器访问列表。IEnumerable接口使实现它的类有一个返回一个IEnumerable接口的GetEnumerator方法。
反过来, IEnumerator提供一个简单的接口,用来提供一个向前的迭代。IEnumerator接口的详细内容在表4-2(显示属性)和4-3(显示方法)。
表 4-2 IEnumerator Properties
名称 描述
Current 得到当前在集合中枚举出来的集合项。
表 4-3 IEnumerator Methods
名称 描述
MoveNext 移到集合的下一项。这个方法常用于确定枚举器是否到了集合的最后一项。
Reset 设置集合的第一项以至于MoveNext能从第一项迭代集合。
使用IEnumerator 接口允许你以一种有序的方式去遍历一系列的对象,如:
while (enumerator.MoveNext())
{
Console.WriteLine(enumerator.Current);
}
这个例子显示了从集合中得到一个枚举器的简单模式,并且使用MoveNext 方法去访问集合。从枚举器和中访问Current 属性去返回集合当前的集合项。C#支持以一个更简单的方式做这种相同的迭代:C#提供一个语言级的构造去以一种更简化的模式做相同的迭代:Foreach.通过使用Foreach构造,你能枚举整个列表,如下:
foreach (object item in coll)
{
Console.WriteLine(item);
}
Foreach结构要求你正在枚举集合对象并且为每个集合内的集合项创建集合项的对象。
这个结构依赖于IEnumerable接口.它能够被用于任何实现IEnumerable接口的集合。 迭代过程的一个好处是如果你已知集合内的类型,你能在foreach结构中定义类型从而节省从object类型转化为特定类型的时间,如下:
ArrayList newColl = new ArrayList();
newColl.Add("Hello");
newColl.Add("Goodbye");
foreach (string item in newColl)
{
Console.WriteLine(item);
}
因为你知道这个集合内的所有项都是字符串,你定义string作为集合项的类型去迭代。如果集合中有一项不是string类型,.NET Framework就会抛出一个类型转换的异常。
Consistent Interfaces in Collections
就像以前的部分所说的, IEnumerable 接口被用于提供一个公共方法去迭代一个集合。还有,
.NET Framework 支持一个通用接口用于集合的应用程序接口。这个接口是
ICollection, 而且它继承IEnumerable 接口. 这意味着每个实现ICollection 接口的集合都必须实现IEnumerable 接口.这个接口的目的是确保每个集合支持一个公共方法,而这个公共方法能把这个集合拷贝到一个Array对象中。ICollection接口最重要的属性和方法是,如表4-4和表4-5
表 4-4 ICollection Properties
Name Description
Count 得到集合内的集合项的个数。
IsSynchronized 得到这个集合是否是线程安全的指示器。
SyncRoot Gets an object that can be used to synchronize the
collection
表 4-5 ICollection Methods
Name Description
CopyTo 把集合内的内容拷贝到数组里。
对于简单的列表集合(如ArrayList),For simple list collections (such as ArrayList), the .NET Framework 支持另一个接口,这个接口用于显示集合项的列表。这个接口是
IList ,它直接继承ICollection 接口. 如果一个类实现IList 接口,那么它必须实现ICollection 和 IEnumerable. 接口的一致性简化了集合的使用。IList 接口的大部分成员在这一点上让你看起来简化了集合的使用。在这章中“添加和删除”部分中,大部分的的属性和方法已被ArrayList 类所实现。这个IList接口的最重要的属性和方法如下:
表 4-6 IList 属性
Name Description
IsFixedSize 得到这个集合是否可以改变大小的指示器。
IsReadOnly 得到这个集合是否能被改变的指示器。
Item 得到和设置集合内的一个特定索引器中的一个数据项。
表 4-7 IList 方法
Name Description
Add 向集合中加一个集合项。
Clear 清空集合
Contains 测试一个特定的集合项是否存在于一个集合中。
IndexOf 寻找集合中的一个集合项,并返回这个集合项的索引值。
Insert 向集合中索引添加一个集合项。Adds an item at a
Remove 删除集合中第一个特定对象。
RemoveAt 删除集合中特点索引的集合项。
集合项的排序
ArrayList支持一个方法去为集合项排序。为了在一个ArrayList中排序,简单的调用ArrayList 中的Sort方法:
coll.Sort();
Sort 方法通过以Comparer类去做比较。Comparer类是一个实现IComparer接口的类。这个接口指示了你要实现一个的方法,这个方法有两个参数(如,a和b)并且返回一个整型值代表比较的结果。结果解释如下:
表4-8 比较结果
Value Condition
小于零 左边的对象小于右边的对象
零 两个对象相等。
大于零 左边的对象大于右边的对象
Sort 方法允许你使用一个IComparer对象做参数,而不用默认无参数。比如,不用Comparer 类,而用CaseInsensitiveComparer类,可实现大小写不敏感的比较:
coll.Sort(new CaseInsensitiveComparer());
写你自己的比较器相对比较简单,因为你仅仅需要实现IComparer 接口中的Compare 方法。比如,如果你想要反转比较(导致集合降序排序),你可以写一个快速的比较器,如下:
public class DescendingComparer : IComparer
{
CaseInsensitiveComparer _comparer = new CaseInsensitiveComparer();
public int Compare(object x, object y)
{
// Reversing the compared objects to
// get descending comparisons
return _comparer.Compare(y, x);
}
}
这个类实现了IComparer 接口. 在Compare 方法中, 我们简单的通过改变参数的位置就得到了相反的排序。然后,我们能使用新的比较对象去降序地排列我们的集合。
coll.Sort(new DescendingComparer());
浙公网安备 33010602011771号