C#中的集合
一、集合的概念
数组可以保存多个对象,但在某些情况下无法确定到底需要保存多少个对象,由于数组的长度不可变,因此数组将不再适用。
如何保存数目不确定的对象呢?
为了保存这些数目不确定的对象,C#中提供了一系列特殊的类,这些类可以存储任意类型的对象,并且长度可变,统称为集合。
集合分类:
可分为非泛型集合和泛型集合,二者均间接实现了IEnumerable接口。
(1)非泛型集合
非泛型集合位于System.Collections命名空间,它可以存储多种类型的对象,其中最常用的是ArrayList集合和Hashtable集合。
(2)泛型集合
泛型集合位于System.Collections.Generic命名空间,它只能存储同一种类型的对象,其中最常用的是List < T > 泛型集合和 Dictionary<TKey,TValue> 泛型集合。
二、非泛型集合类ArrayList
ArrayList可以容纳不同类型的对象
这些对象包括int、string、object等类型的对象
同时也提供一系列添加、删除、修改和查询元素等操作方法
int Add(object value) |将元素添加到ArrayList集合,并且该元素可以是null,且允许重复值,返回值为所插入位置的索引值
void AddRange(ICollection c) |将集合或者数组添加到ArrayList集合
void Clear() |从ArrayList中移除所有元素
bool Contains(object item) |判断某元素是否在ArrayList中
int IndexOf(object value) |查找指定元素,并返回该元素在ArrayList中第一个匹配项的索引
void Insert(int index,object value) |将元素插入ArrayList的指定索引处
int LastIndexOf(object value) |查找指定元素,并返回该元素在ArrayList中最后一个匹配项的索引
void Remove(object obj) |从ArrayList中移除指定元素的第一个匹配项
void RemoveAt(int index)|从ArrayList中移除指定索引处的元素
void Reverse() |将整个ArrayList中元素的顺序反转
void Sort() |对整个ArrayList中的元素进行排序,由小到大
//创建ArrayList集合对象arr
ArrayList arr = new ArrayList();
//使用不同方法向集合添加多个元素
arr.Add(222);
arr1.AddRange(new ArrayList() { "小明", "小红" });
arr1.Insert(2, 'a');
集合的长度就是元素的个数,集合的容量是随集合长度变化而变化的。如果集合的长度在1-5之间。容量的值就是5。
三、foreach循环
虽然for循环可以用于遍历集合中的元素,但写法上比较繁琐,foreach在遍历时无需循环条件
foreach (var item in collection)
{
执行语句;
}
item变量用于存储每次遍历的元素(默认情况下item为var类型),in为关键字,collection是被遍历的集合。
foreach循环的次数是由元素的个数决定的,每一次循环时,foreach中都通过变量将当前循环中的元素记住,从而将集合中的元素遍历输出。
可以说foreach循环是专门用于遍历数组和集合的循环语句。
但注意,foreach循环只能对遍历到的元素进行读操作,且之能单向遍历,也就是一个元素在整个foreach循环内只能被访问一次。
Hashtable集合——非泛型集合类
在ArrayList集合中查找某个元素时,是从索引位置为0的元素开始逐一进行比对的,这样的查询效率很低,为此C#提供了一个Hashtable集合,该集合又被称为键值对集合。
void Add(object key,object value) 将带有指定键和值的元素添加到Hashtable中
void Clear() 从Hashtable中移除所有元素
bool Contains(object key) 判断Hashtable中是否包含指定的键
bool ContainsValue(object value) 判断Hashtable是否包含指定的值
void Remove(object key) 从Hashtable中移除带有指定键的元素
在Hashtable集合中的键和值的默认类型都是object,因此可以向键和值中添加任意类型的对象。在遍历Hashtable集合时,除了可以通过键来获取对应的值以外,还可以直接遍历集合的值或者集合对象
Hashtable ht = new Hashtable();
//调用Hashtable的Add()方法来添加元素
ht.Add(1, "小张");
ht.Add(2, "小赵");
ht.Add(3, "小钱");
//使用foreach语句来循环遍历集合中的值
foreach (object value in ht.Values)
{
Console.WriteLine("当前遍历到的值为:" + value);
}
Console.WriteLine();
//使用foreach语句来循环遍历集合对象本身
foreach (DictionaryEntry dicEn in ht)
{
Console.Write(dicEn.Key + ":" + dicEn.Value + "\n");
}
Console.ReadKey();
在遍历集合对象本身时,集合对象是DictionaryEntry类型,通过该类型的对象dicEn既可以获得键,也可以获得值。
List泛型集合
ArrayList集合与Hashtable集合可以存储多种类型的元素,由于集合中的元素类型不一致,在很多情况下,使用foreach循环获取集合中的元素时,需要对它们进行强制类型转换,这种操作大大降低了程序的执行效率。
C#中提出了泛型集合的概念,泛型集合相当于与集合制定了某个限制条件,这个条件使集合中只能存储一种类型的元素。
List< T > 是一种常用的泛型集合,T值某种数据类型,如int、string等,该集合不仅具备ArrayList集合的功能,而且还可以保证List< T >集合只能添加同类型元素,不会出现类型转换的问题。
除此以外,List< T >泛型集合不仅具有ArrayList集合的方法,而且还具有一些特有方法,如Max()、Min()、Sum()方法等
List<int> list = new List<int>(new int[] { 1, 2, 3, 4, 5, 6 });
//获取集合中的最大值
int max = list.Max();
//获取集合中的最小值
int min = list.Min();
//获取集中元素的总和
int sum = list.Sum();
Dictionary<Tkey,TValue>泛型集合
Hashtable集合中的键与值在默认情况下都是object类型,这使得用户在取值时不可避免的遇到类型转换的问题,因此C#提供了Dictionary<Tkey,TValue>泛型集合,该集合中的键和值都只能是一种类型。
Dictionary<int, string> dic = new Dictionary<int, string>();
//通过遍历集合中的键获取对应的值
foreach (int key in dic.Keys)
//通过遍历键值对的方式来获取键与值
foreach (KeyValuePair<int, string> kv in dic)
Dictionary<Tkey, TValue >集合的键值对类型为KeyValuePair<int,string> ,通过该类型的对象就可以获取集合中的键和值。
自定义泛型
在程序开发中,如果List< T > 泛型集合和Dictionary<Tkey,TValue>泛型集合都不能满足实际需求,还可以自定义泛型。自定义泛型可以根据用户的不同需求,灵活的设计属性和方法。
语法格式如下:
[修饰符] class类名<类型占位符>
{
程序代码
}
自定义泛型与普通类的语法格式相似,唯一的区别就是多了一个类型占位符。类型占位符通常用T来表示,可以自行修改,但要遵循变量的命名规范。
static void Main(string[] args)
{
//创建自定义泛型对象myClass
MyClass<string> myClass = new MyClass<string>();
//调用Add()方法添加一个元素
myClass.Add("小小");
Console.WriteLine("自定义泛型中的元素:" + myClass.Get());
Console.ReadKey();
}
}
//自定义泛型MyClass<T>
class MyClass<T>
{
T myElement; //定义一个T类型字段
public void Add(T elem) //创建Add()方法,指定参数类型为T
{
this.myElement = elem;
}
public T Get() //创建Get()方法,指定返回类型为T
{
return this.myElement;
}
}
首先在定义MyClass< T >类中,设置类型占位符为T。在Main()方法中实例化对象myClass时,通过< string >将T指定为string类型。