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类型。