8.集合
8.1 简介
集合与数组比较类似,都用于存放一组值,但集合中提供了特定的方法能直接操作集合中的数据,并提供了不同的集合类来实现特定的功能。所有集合类或与集合相关的接口命名空间都是System.Collection
,在该命名空间中提供的常用接口
如下表所示。
接口名称 | 作用 |
---|---|
IEnumerable | 用于迭代集合中的项,该接口是一种声明式的接口 |
IEnumerator | 用于迭代集合中的项,该接口是一种实现式的接口 |
ICollection | .NET 提供的标准集合接口,所有的集合类都会直接或间接地实现这个接口 |
IList | 继承自IEnumerable和ICollection接口,用于提供集合的项列表,并允许访问、查找集合中的项 |
IDictionary | 继承自IEnumerable和ICollection接口,与IList接口提供的功能类似,但集合中的项是以键值对的形式存取的 |
IDictionaryEnumerator | 用于迭代IDictionary接口类型的集合 |
针对上表中的接口有一些常用的接口实现类,如下表所示。
类名称 | 实现接口 | 特点 |
---|---|---|
ArrayList | ICollection、IList、IEnumerable、ICloneable | 集合中元素的个数是可变的,提供添加、删除等方法 |
Queue | ICollection、IEnumerable、ICloneable | 集合实现了先进先出的机制,即元素将在集合的尾部添加、在集合的头部移除 |
Stack | ICollection、IEnumerable、ICloneable | 集合实现了先进后出的机制,即元素将在集合的尾部添加、在集合的尾部移除 |
Hashtable | IDictionary、ICollection、IEnumerable、 ICloneable 等接口 | 集合中的元素是以键值对的形式存放的,是DictionaryEntry类型的 |
SortedList | IDictionary、ICollection、IEnumerable、 ICloneable 等接口 | 与Hashtable集合类似,集合中的元素以键值对的形式存放,不同的是该集合会按照 key 值自动对集合中的元素排序 |
8.2 ArrayList类:动态数组
ArrayList代表了可被单独索引的对象的有序集合。它基本上可以替代一个数组。但与数组不同的是,ArrayList可以使用索引在指定的位置添加和移除项目,动态数组会自动重新调整它的大小。
创建ArrayList类的对象需要使用该类的构造方法,如下表所示。
构造方法 | 作用 |
---|---|
ArrayList() | 创建 ArrayList 的实例,集合的容量是默认初始容量 |
ArrayList(ICollection c) | 创建 ArrayList 的实例,该实例包含从指定实例中复制的元素,并且初始容量与复制的元素个数相同 |
ArrayList(int capacity) | 创建 ArrayList 的实例,并设置其初始容量 |
// 在创建类的实例后,集合中还未存放值
ArrayList listl=new ArrayList();
ArrayList list2=new ArrayList(listl);
ArrayList list3=new ArrayList(20);
// 在创建集合实例时向集合中添加元素
ArrayList list4 = new ArrayList(){l,2,3,4};
集合与数组一样也能使用foreach语句遍历元素。
foreach(var v in list4)
{
Console.WriteLine(v);
}
ArrayList类中常用的属性和方法如下表所示。
属性或方法 | 作用 |
---|---|
Capacity | 属性,用于获取或设置集合中可以包含的元素个数 |
Count | 属性,用于获取集合中实际含有的元素个数 |
int Add(object value) | 向集合中添加object类型的元素,返回元素在集合中的下标 |
void AddRange(ICollection c) | 向集合中添加另一个集合c |
void Clear() | 从集合中移除所有元素 |
bool Contains(object item) | 判断集合中是否含有item元素,若含有该元素则返回True,否则返回False |
void CopyTo(Array array) | 从目标数组array的第0个位置开始,将整个集合中的元素复制到类型兼容的数组array中 |
void CopyTo(Array array,int arraylndex) | 从目标数组array的指定索引arraylndex处,将整个集合中的元素赋值到类型兼容的数组array中 |
void CopyTo(int index,Array array,int arrayIndex,int count) | 从目标数组array的指定索引arrayindex处,将集合中从指定索引index开始的count个元素复制到类型兼容的数组array中 |
int IndexOf(object value) | 返回value值在集合中第一次出现的位置 |
int IndexOf(object value,int startIndex) | 返回value值在集合的startindex位置开始第一次出现的位置 |
int IndexOf(object value,int startIndex,int count) | 返回value值在集合的startindex位置开始count个元素中第一次出现的位置 |
int LastIndexOf(object value) | 返回value值在集合中最后一次出现的位置 |
int LastIndexOf(object value,int startIndex) | 返回value值在集合的startindex位置开始最后一次出现的位置 |
int LastIndexOf(object value,int startIndex,int count) | 返回元素value值在集合的startindex位置开始count个元素中最后一次出现的位置 |
void Insert(int index,object value) | 向集合中的指定索引index处插入value值 |
void InsertRange(int index,ICollection c) | 向集合中的指定索引index处插入一个集合 |
void Remove(object obj) | 将指定元素obj从集合中移除 |
void RemoveAt(int index) | 移除集合中指定位置index处的元素 |
void RemoveRange(int index,int count) | 移除集合中从指定位置index处的 count 个元素 |
void Reverse() | 将集合中的元素顺序反转 |
void Reverse(int index,int count) | 将集合中从指定位置index处的count个元素反转 |
void Sort() | 将集合中的元素排序,默认从小到大排序 |
void Sort(IComparer comparer) | 将集合中的元素按照比较器comparer的方式排序 |
void Sort(int index,int count,IComparer comparer) | 将集合中的元素从指定位置index处的count个元素按照比较器comparer的方式排序 |
void TrimToSize() | 将集合的大小设置为集合中元素的实际个数 |
using System;
using System.Collections;
class Program
{
static void Main(string[] args)
{
ArrayList list = new ArrayList() { "aaa", "bbb", "abc", 123, 456 };
Console.Write("List:");
foreach (var v in list)
{
Console.Write(v + "\t");
}
Console.WriteLine();
// 查找集合中的元素
int index = list.IndexOf("abc");
if (index != -1)
{
Console.WriteLine("集合中存在 abc 元素!");
}
else
{
Console.WriteLine("集合中不存在 abc 元素!");
}
// 将集合中下标为偶数的元素添加到另一个集合中
ArrayList newList = new ArrayList();
for (int i = 0; i < list.Count; i = i + 2)
{
newList.Add(list[i]);
}
Console.Write("newList:");
foreach (var v in newList)
{
Console.Write(v + "\t");
}
Console.WriteLine();
// 在集合中的第一个元素后面添加元素
ArrayList insertList = new ArrayList() { "A", "B", "C" };
list.InsertRange(1, insertList);
Console.Write("在List的第一个元素后添加元素:");
foreach (var v in list)
{
Console.Write(v + "\t");
}
Console.WriteLine("");
// 对集合中的元素排序,需要元素转换为同一类型才能比较,否则会出现无法比较的异常
ArrayList list1 = new ArrayList() { "aaa", "bbb", "abc" };
Console.Write("List1:");
foreach (var v in list1)
{
Console.Write(v + "\t");
}
Console.WriteLine();
list1.Sort();
Console.Write("排序后:");
foreach (var v in list1)
{
Console.Write(v + "\t");
}
}
}
8.3 Queue类:队列
Queue(队列)是常见的数据结构之一,队列是一种先进先出的结构,即元素从队列尾部插入,从队列的头部移除,类似于日常生活中的站队,先到先得的效果。
构造方法 | 作用 |
---|---|
Queue() | 创建Queue的实例,集合的容量是默认初始容量32个元素,使用默认的增长因子 |
Queue(ICollection col) | 创建Queue的实例,该实例包含从指定实例中复制的元素,并且初始容量与复制的元素个数、增长因子相同 |
Queue(int capacity) | 创建Queue的实例,并设置其指定的元素个数,默认增长因子 |
Queue(int capacity, float growFactor) | 创建Queue的实例,并设置其指定的元素个数和增长因子 |
增长因子是指当需要扩大容量时,以当前的容量(capacity)值乘以增长因子(growFactor)的值来自动增加容量。
//四种队列构造方法
Queue queueq1 = new Queue();
Queue queueq2 = new Queue(queue1);
Queue queueq3 = new Queue(30);
Queue queueq4 = new Queue(30, 2);
与ArrayList 类不同,Queue类不能在创建实例时直接添加值。Queue类中常用的属性和方法如下表所示。
属性或方法 | 作用 |
---|---|
Count | 属性,获取Queue实例中包含的元素个数 |
void Clear() | 清除Queue实例中的元素 |
bool Contains(object obj) | 判断Queue实例中是否含有obj元素 |
void CopyTo(Array array, int index) | 将array数组从指定索引处的元素开始复制到Queue实例中 |
object Dequeue() | 移除并返回位于Queue实例开始处的对象,即出队 |
void Enqueue(object obj) | 将对象添加到Queue实例的结尾处,即入队 |
object Peek() | 返回位于Queue实例开始处的对象但不将其移除 |
object[] ToArray() | 将Queue实例中的元素复制到新数组 |
void TrimToSize() | 将容量设置为Queue实例中元素的实际数目 |
IEnumerator GetEnumerator() | 返回循环访问Queue实例的枚举数 |
using System;
using System.Collections;
class Program
{
static void Main(string[] args)
{
Queue queue = new Queue();
//向队列中加入3为购票人
queue.Enqueue("小张");
queue.Enqueue("小李");
queue.Enqueue("小刘");
Console.WriteLine("购票开始:");
//当队列中没有人时购票结束
while (queue.Count != 0)
{
Console.WriteLine(queue.Dequeue() + "已购票!");
}
Console.WriteLine("购票结束!");
}
}
// 购票开始:
// 小张已购票!
// 小李已购票!
// 小刘已购票!
// 购票结束!
8.4 Stack类:堆栈
Stack(栈)是常见的数据结构之一,栈是一种先进后出的结构,即元素从栈的尾部插入,从栈的尾部移除。
构造方法 | 作用 |
---|---|
Stack() | 使用初始容量创建Stack的对象 |
Stack(ICollection col) | 创建Stack的实例,该实例包含从指定实例中复制的元素,并且初始容量与复制的元素个数、增长因子相同 |
Stack(int capacity) | 创建Stack的实例,并设置其初始容量 |
Stack 类中的常用属性和方法如下表所示。
属性或方法 | 作用 |
---|---|
void Push(object obj) | 向栈中添加元素,也称入栈 |
object Peek() | 用于获取栈顶元素的值,但不移除栈顶元素的值 |
object Pop() | 用于移除栈顶元素的值,并移除栈顶元素 |
void Clear() | 从Stack中移除所有的元素 |
bool Contains(object obj) | 判断某个元素是否在Stack中 |
object[] ToArray() | 复制Stack到一个新的数组中 |
using System;
using System.Collections;
class Program
{
static void Main(string[] args)
{
Stack stack = new Stack();
//向栈中存放元素
stack.Push("1号盘子");
stack.Push("2号盘子");
stack.Push("3号盘子");
stack.Push("4号盘子");
stack.Push("5号盘子");
Console.WriteLine("取出盘子:");
//判断栈中是否有元素
while(stack.Count != 0)
{
//取出栈中的元素
Console.WriteLine(stack.Pop());
}
}
}
// 取出盘子:
// 5号盘子
// 4号盘子
// 3号盘子
// 2号盘子
// 1号盘子
8.5 Hashtable类:哈希表
Hashtable类实现了IDictionary接口,集合中的值都是以键值对(key/value)的形式存取的。
// 构造方法
Hashtable 对象名 = new Hashtable ();
Hashtable 类中常用的属性和方法如下表所示。
属性或方法 | 作用 |
---|---|
Count | 集合中存放的元素的实际个数 |
void Add(object key,object value) | 向集合中添加元素 |
void Remove(object key) | 根据指定的key值移除对应的集合元素 |
void Clear() | 清空集合 |
bool ContainsKey (object key) | 判断集合中是否包含指定key值的元素 |
bool ContainsValue(object value) | 判断集合中是否包含指定value值的元素 |
using System;
using System.Collections;
class Program
{
static void Main(string[] args)
{
Hashtable ht = new Hashtable();
ht.Add(1, "计算机基础");
ht.Add(2, "C#高级编程");
ht.Add(3, "数据库应用");
Console.WriteLine("请输入图书编号");
int id = int.Parse(Console.ReadLine());
bool flag = ht.ContainsKey(id);
if (flag)
{
Console.WriteLine("您查找的图书名称为:{0}", ht[id].ToString());
}
else
{
Console.WriteLine("您查找的图书编号不存在!");
}
Console.WriteLine("所有的图书信息如下:");
foreach (DictionaryEntry d in ht)
{
int key = (int)d.Key;
string value = d.Value.ToString();
Console.WriteLine("图书编号:{0},图书名称:{1}", key, value);
}
}
}
8.6 SortedList类:有序列表
SortedList类实现了IDictionary接口 ,集合中的值都是以键值对的形式存取的。它称为有序列表,按照key值对集合中的元素排序,与Hashtable比较类似。
using System;
using System.Collections;
class Program
{
static void Main(string[] args)
{
SortedList sortList = new SortedList();
sortList.Add(1, "小张");
sortList.Add(2, "小李");
sortList.Add(3, "小刘");
Console.WriteLine("请输入挂号编号:");
int id = int.Parse(Console.ReadLine());
bool flag = sortList.ContainsKey(id);
if (flag)
{
string name = sortList[id].ToString();
Console.WriteLine("您查找的患者姓名为:{0}", name);
}
else
{
Console.WriteLine("您查找的挂号编号不存在!");
}
Console.WriteLine("所有的挂号信息如下:");
foreach (DictionaryEntry d in sortList)
{
int key = (int)d.Key;
string value = d.Value.ToString();
Console.WriteLine("挂号编号:{0},姓名:{1}", key, value);
}
}
}