Web开发之C#:(9)C#常用类库2:集合

作者:陆金龙    发表时间:2016-07-21 00:35   


2.集合

2.1集合—ArrayList(“动态数组”)

引子:数组的长度是分配好的,不可以随时变化。集合的长度是可变的。

ArrayList:使用大小可按需动态增加的数组实现 IList 接口,集合中项(items)的类型是object的类型,即可以是各种不同的类型。

(1)增:Add()、AddRange()、Insert()、InsertRange()

int[] nums = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };

ArrayList arraylist = new ArrayList();

arraylist.Add("一个集合");

arraylist.Add(123);

arraylist.Add(nums);          //整个数组作为一个元素加进去

arraylist.AddRange(nums);     //将数组的每个元素依次加进去

arraylist.Insert(3, 999);        //在集合的索引为3的位置插入一个元素

arraylist.InsertRange(1, nums);  //在集合索引为1的位置,将数组元素依次加进去

arraylist.Add(123);

arraylist.Add("我是一个集合");

 

(2)删:Clear()、RemoveAt()、RemoveRange()、Remove()

arraylist.Clear();             //删除集合中的所有元素

arraylist.Remove(123);        //移除集合中的第一个“123”的匹配项

arraylist.RemoveAt(3);        //移除集合中的索引为3的元素

arraylist.RemoveRange(6, 2);   //从集合中的索引为6的元素起,移除两个元素

 

(3)改:使用索引(同字符串)

arraylist[3] = "aaabbb";         //修改集合中的元素的值

 

(4)查:IndexOf、lastIndexOf、Contains(同字符串)

  object arr1=arraylist[18];

      int index1=arraylist.LastIndexOf(123);

int index2=arraylist.LastIndexOf("我是一个集合");

  bool flag1=arraylist.Contains("123");

bool flag1=arraylist.Contains(123);

 

(5)综合应用

  (A)Contains应用——添加项时过滤重复项

            ArrayList arr1 = new ArrayList { "a", "b", "c", "d", "e" };

            ArrayList arr2 = new ArrayList { "d", "e", "f", "g", "h", };

            for (int i = 0; i < arr2.Count; i )

            {

                if (!arr1.Contains(arr2[i]))

                  arr1.Add(arr2[i]);

             }

  (B)产生10个1-100的随机数加入到集合中,要求这10个数不重复,且为偶数

            ArrayList arrlist = new ArrayList();

Random r = new Random();

            for (int i = 0; list.Count < 10; i )

            {

                int num = r.Next(1, 101);  //1<= num<101

                if (num%2==0&&!(arrlist.Contains(num)))

                {

                    arrlist.Add(num);

                }

            }

 

2.2集合—HashTable(键值对集合)

引子:处理符合键值对特征的数据,实现快速查找。

//普通的集合(有序),查找使用简单遍历,效率不高。

ArrayList arrlist = new ArrayList();

arrlist.Add(new Person("张三", "732492380"));// arrlist[0]

arrlist.Add(new Person("张三1", "73422380"));// arrlist[1]

arrlist.Add(new Person("张三2", "7324232380"));// arrlist[2]

HashTable:是无序的集合,通过键来快速定位查找。

 

(1)增:Add( )、Table[key] = value(使用索引实现添加数据);  

     Hashtable table = new Hashtable();

     table['d'] = "大先生";

     table.Add('m',"先生");

     table.Add('f',"小姐");     

 

(2)删:Clear( )、Remove(key ) (Hashtable的元素无序,删除没有“At”和“Range”)

table.Clear();

table.Remove('a');

 

(3)改:Table[key] = value; 使用键索引!

table['d'] = "大先生";

 

(4)查:Table[key]、ContainsKey( )、ContainsValue( ) 。键是用来查找的,所以不允许重复。

objectobj=table['m'];

bool flag1=table.ContainsKey('z')

bool flag2=table.ContainsValue("西西")

 

附:集合应用之分拣奇偶数(将字符串内容重新排序奇数在前偶数在后)

        static void Main(string[] args)

        {

            string str = "27 9 8 33 2 29 57 28";//处理成"27 9 33 29 57 8 2 28"

            string[] strs = str.Split(' ');

            ArrayList arrOdd = new ArrayList();

            ArrayList arrEven = new ArrayList();

            for (int i = 0; i < strs.Length; i )

            {

                int num = Convert.ToInt32(strs[i]);

                if (num % 2 == 0)

                {

                    arrEven.Add(strs[i]);//偶数

                }

                else

                {

                    arrOdd.Add(strs[i]);//奇数

                }

            }

            arrOdd.AddRange(arrEven);

str = string.Join(" ", arrOdd.ToArray());   //方法1:VS2008不可以,VS2010可以

 

StringBuilder sb = new StringBuilder();

            for (int i = 0; i < listOdd.Count - 1;i )

            {

                sb.Append(string.Format("{0}  ", listOdd[i]));

            }

            sb.Append(listOdd[listOdd.Count - 1]);

string res = sb.ToString();              //方法2:VS2008可以,VS2010可以

 

//得到string类型元素的数组,需强制转换为子类类型string[]

            string[] ss = (string[])arrOdd.ToArray(typeof(string));  

            string s =string.Join(" ", ss); //方法3:VS2008可以,VS2010可以

2.3集合—泛型集合

引子:ArrayList和HashTable元素的类型是object,使用中经常需要做类型转换。

string strnum = "2 9 8 3 2 2 7 8";

string[] strArr=strnum.Split(' ');

ArrayList arrlist = newArrayList();

     arrlist.AddRange(strArr);

Array arr =arrlist.ToArray(typeof(string));

string[] ss = (string[])arr;

//如果上面ToArray方法不使用typeof(string),则得到的Object类型的数组,转换出错

//无法将类型为“System.Object[]”的对象强制转换为类型“System.String[]”

 

char[] charArr = { '2', '4', 'h', '4', '3', 'd' };

ArrayList arrlist1 = newArrayList();

arrlist1.AddRange(charArr);

Array arr1 = arrlist1.ToArray(typeof(char));

char[] c = (char[])arr1;   

//如果ToArray方法中不使用typeof(char),则得到的Object类型的数组,转换出错

//无法将类型为“System.Object[]”的对象强制转换为类型“System.Char[]”

如果一个集合中存放的多种类型的数据,转换时还可能出现异常。

 

泛型集合:泛型集合的出现正是考虑到集合中类型问题的不方便。

泛型集合先指定类型,再使用,避免了使用过程中的类型转换。

命名空间:System.Collections.Generic;

使用泛型集合前,指定集合类型,在尖括号中填入需要使用的类型,这个集合就是专门为这个类型定制的集合,所有方法使用的参数均会变成相关的类型。

1)List<T>集合(对应ArrayList,使用类似)

List<string> liststr = new List<string>();

List<char> listchar = new List<char>();

List<Person> listper = new List<Person>();

Add()方法,自动匹配参数类型。

ToArray()方法,自动返回相应类型的数组,不需要指定typeof参数了

liststr.ToArray();  //返回string[]类型数组

listchar.ToArray(); //返回char[]类型数组

listper.ToArray();  //返回Person[]类型数组

2)Dictionary<TKey,TValue>集合(对应HashTable,使用类似)

应用:参考以下foreach。

2.4 集合的遍历foreach( )

像HashTable、Dictionary这样的无序集合,无法通过数字来索引,不能用for循环实现遍历只能采用Foreach( )来遍历。(有序集合则可以使用for循环或者Foreach())

注:KeyValuePair<TKey, TValue>是泛型结构,只能对应Dictionary的foreach输出,而不能是非泛型的HashTable的。

语法:public struct KeyValuePair<TKey, TValue>

C# 语言中的 foreach 语句需要集合中的元素类型,是 KeyValuePair(TKey, TValue) 类型。

因为基于 IDictionary(TKey, TValue) 的集合中的每个元素都是一个键/值对,因此元素类型既不是键的类型,也不是值的类型。

1)HashTable的foreach( )输出

    Hashtable table = new Hashtable();

    table.Add("张无忌", new Person("张无忌", "13423234923"));

    table.Add("赵敏", new Person("赵敏", "1347237864923"));

    foreach (string item in table.Keys)   //输出键

    {

         Console.WriteLine(item);

    }

    foreach (Person p in table.Values)   //输出值

    {

         Console.WriteLine("{0}\t{1}",p.Name,p.Phone);

}

    foreach (DictionaryEntry o in table)  //输出键和值

    {

         Console.WriteLine("{0}\t{1}", o.Key, o.Value);  //o.Value只得到Person类型,没有得到成员

    }

2)Dictionary的foreach( )输出

     Dictionary<string,Person> dic = new Dictionary<string,Person>();

     dic.Add("张无忌", new Person("张无忌", "13423234923"));

     dic.Add("赵敏", new Person("赵敏", "1347237864923"));

     foreach (KeyValuePair<string, Person> kvp in dic)

     {

         Console.WriteLine("{0}\t{1}\t{2}", kvp.Key, kvp.Value.Name,kvp.Value.Phone);

 //泛型的好处,得到了Person的成员!

     }