C#面向对象_7_集合

集合

复习foreach

string[] strArr = new string[] { "小白", "小黑", "小黄", "小红", "小强" };
            foreach (string s in strArr)
                Console.WriteLine(s);

集合

C#中,集合和数组都可以用存储多个数据元素,但是集合比数组更加灵活,比如:集合可以动态的添加和删除其中的元素。但数组要实现这一点就非常的麻烦和死板了。

集合的种类

ArrayList动态数组、stcak堆栈、queue队列、sortList排序列表、HashTable哈希表

堆栈

堆栈它是一个存储数据的容器,我们可以想像这个容器就像一个弹夹或瓶子,最先放入的数据在最底下,最后放入的数据在最上面。也就是:“先入后出,后入先出”。

堆栈本质是stack类,向堆栈中加一个数据叫做入栈,取出一个数据叫出栈。

语法定义

Stack 堆栈名 = new Stack();

Stack的常用属性

Count 所包含的元素个数

Stack的常用方法

clear() 清除集合中的所有元素

Contains(object obj) 判断某个元素是否包含在当前集合中

Peek() 返回堆栈最上面的一个元素,但是该元素仍然处于原位置,不会被移除。

pop() 返回堆栈最上面的一个元素,并且 在堆栈中移除该元素,就好像是将它取出一样。

push() 向堆栈最上面添加一个元素。

toArray() 将集合转换为一个数组,并返回这个数组。

快速引用命名空间的小技巧

堆栈位于命名空间 System.Collections,我们可以按如下方法添加该命名空间:

先写入完整的类名(注意大小写)

在类名上右击à解析à选择相应的命名空间

仅限于.net系统框架自带的内置的类和命名空间。

堆栈示例:

//定义堆栈
            Stack st = new Stack();
            //向堆栈之中添加元素
            //堆栈中的所有元素都会自动转换为object类型,也就是说Stack可以存放任意类型的数据,而不像数组一样必须要求类型一致。
            st.Push('A');
            st.Push('B');
            st.Push('C');
            st.Push('D');
            st.Push('E');
            foreach (char c in st)       //遍历
                Console.WriteLine(c);
            st.Push('F');
            st.Push('G');
            //peek()不会移除元素
            Console.WriteLine("peek下一个元素是{0}", st.Peek());
            Console.WriteLine("peek下一个元素是{0}", st.Peek());
            //pop()会移除最上面的元素
            Console.WriteLine("pop下一个元素是{0}", st.Pop());
            Console.WriteLine("pop下一个元素是{0}", st.Pop());
            Console.WriteLine("pop下一个元素是{0}", st.Pop());

队列queue

也是存放数据的容器,就像去超市付款的时候排列一样,先入先出,后入后出。

队列的本质是Queue类,向队列中加入一条数据叫做入队,取出一条数据叫出队。

语法定义

Queue 队列名 = new Queue();

Queue的常用属性

Count 所包含的元素个数

Queue的常用方法

clear() 清除集合中的所有元素

Contains(object obj) 判断某个元素是否包含在当前集合中

toArray() 将集合转换为一个数组,并返回这个数组。

Dequeue() 出队,返回队列最前面的一个元素,并且在队列中移除该元素,就好像是将它取出来一样。

Enqueue() 入队,在队列最后添加一个元素。

TrimToSize 设置队列的实际容量个数。

Queue示例:

 //定义队列
            Queue q = new Queue();
            q.Enqueue('A');
            q.Enqueue('B');
            q.Enqueue(67);
            q.Enqueue(68);
            Console.WriteLine("当前队列为:");
            foreach (object a in q)
                Console.WriteLine(a.ToString());
            q.Enqueue('E');
            q.Enqueue('F');
            Console.WriteLine("添加两个元素之后的队列为:");
            foreach (object a in q)
                Console.WriteLine(a.ToString());
            Console.WriteLine("{0}已经出队", q.Dequeue());
            Console.WriteLine("{0}已经出队", q.Dequeue());
            Console.WriteLine("{0}已经出队", q.Dequeue());
            foreach (object a in q)
                Console.WriteLine(a.ToString());

小技巧

VS中按F12,就可以跳转到当前光标所在位置的变量、类、对象、方法、接口等等元素的被定义的代码处。

ICollection和IEnumerable接口

所有集合都继承并实现了这两个接口

IEnumerable接口:只要继承了该接口,就必须实现GetEnumerator()方法以便能够被循环遍历访问。

ICollection接口:包含Count等多个方法,子类必须能够实现统计元素个数的功能。

ArrayList

也称为动态数组,它可以用来替代数组,而且它比数组更加灵活,它允许动态的对数组元素进行添加、删除、排序、搜索等操作。

它和数组一样,都为元素分配了下标,而且下标会根据数据元素的改变而自动重新分配。

ArrayList的常用属性

属性

描述

Capacity

获取或设置ArrayList可包含的元素个数

Count

ArrayList中实际包含的元素个数

IsReadOney

表示ArrayList是否只读

Item

获取可设置指定索引的元素的值,就是根据下标来得到数据元素。

IsFixedSize

表示ArrayList的容量是否固定

ArrayList的常用方法

方法

描述

int Add(object value)

ArrayList的未尾添加一个元素。(该元素会自动被转换为object类型)

void AddRange(ICollection c )

ArrayList的未尾添加另一个集合(实现了ICollection接口)中的所有元素。

void clear()

移除集合中的所有元素,清空

bool Contains(object value)

判断一个元素是否包含在ArrayList

ArrayList GetRange(int index,int count)

从当前ArrayList中返回一个子集,包含了从下标index开始的count个元素。

int Indexof(object)

返回某个值在ArrayList中第一次出现的索引(下标),实际上就是搜索一个元素。

void insert(int index,object value)

ArrayList的指定索引下标位置,插入一个集合中的所有元素。

void Remove(object obj)

根据元素的值来删除第一个匹配的元素

void RemoveAt(int index)

根据下标来删除元素

void RemoveRange(int index,int count)

删除ArrayList中指定范围的元素,从下标index开始的count个元素。

void Reverse()

逆转ArrayList中元素的顺序

void SetRange(int index,ICollection c)

复制某个集合(实现了ICollection接口的集合)到ArrayList指定的下标之后

void Sort()

ArrayList中的元素进行排序

void TrimToSize()

设置ArrayList中的元素的个数

示例:

// ArrayList也是类,因此在使用它之前我们必须要实例化对象:
ArrayList al = new ArrayList();
            //使用Add方法可以添加数据元素
            al.Add(1);
            al.Add(8);
            //所有数据都会被自动"装箱"
            //al.Add("tom");
            //al.Add(false);
            al.Add(9);
            al.Add(4);
            al.Add(0);
            al.Add(6);
            Console.WriteLine("arrayList容量是:" + al.Capacity);
            Console.WriteLine("arrayList元素个数是:" + al.Count);
            //遍历
            foreach (int i in al)
                Console.Write(i + "\t");
            al.Reverse();
            Console.WriteLine();
            Console.WriteLine("颠倒ArrayList中的元素次序");
            foreach (int i in al)
                Console.Write(i + "\t");
            al.Sort();
            Console.WriteLine();
            Console.WriteLine("arrayList排序");
            foreach (int i in al)
                Console.Write(i + "\t");
            al.Insert(2, 100); //在下标为2的位置插入100
            al.RemoveAt(3); //删除下标为3的数值开始。
            Console.WriteLine();
            Console.WriteLine("遍历时显示下标和元素值");
            for (int i = 0; i < al.Count; i++)
                Console.WriteLine("下标:{0}值为:{1}", i, al[i]);
            if (al.Contains(100))
                Console.WriteLine("其中包含100");

小练习:

定义一个student类,该类包含属性 姓名、年龄、性别、电话,并具备一个构造 函数来为这四个属性赋值。然后定义一个arrayList,在arrayList中存放5student对象,遍历显示出这5个学生的信息。最后,删除第三个学生信息。

哈希表

HashTable,其特点是以键值对的方式来存取集合元素。

key和值value组成一个键值对,使用add()方法来添加。

键名不能重复,键值可以重复。

HashTable的属性

属性

描述

Count

HashTable中实际包含的元素个数

IsReadOney

表示HashTable是否只读

Item

获取可设置指定键的元素的值。

IsFixedSize

表示HashTable的容量是否固定

Keys

获取一个ICollection接口的集合,其中包含了Hashtable中的所有键。

Values

获取一个ICollection接口的集合,其中包含了Hashtable中的所有值。

HashTable的常用方法

方法

描述

int Add(object key , object value)

HashTable中添加一个带有键名和键值的元素。

void clear()

移除集合中的所有元素,清空

bool Contains(object value)

判断一个元素是否包含在ArrayList

void Remove(object key)

根据元素的键名来删除第一个匹配的元素

bool ContainsKey(object Key)

判断某个键名是否包含在Hashtable

bool ContainsValue(object value)

判断某个元素的值是否包含在Hashtable

示例1

Hashtable ht = new Hashtable();
            ht.Add("张三", 98.5f);
            ht.Add("李四", 81f);
            ht.Add("王五", 79f);
            ht.Add("赵六", 89f);
            ht.Add("沈七", 65f);
            if (ht.ContainsKey("赵六"))
                Console.WriteLine("赵六是我班同学,他的成绩是" + ht["赵六"]);
            Console.WriteLine("遍历哈希表");
            /*获取键名的集合:实现了ICollection接口的,
             * 用于存放所有键名的集合*/
            ICollection keys = ht.Keys;
            foreach (string k in keys)
                Console.WriteLine("{0}是我班同学,他的成绩是{1}", k, ht[k]);

示例2利用DictionaryEntry

            Hashtable ht = new Hashtable();
            ht.Add("张三", 98.5f);
            ht.Add("李四", 81f);
            ht.Add("王五", 79f);
            ht.Add("赵六", 89f);
            ht.Add("沈七", 65f);
            //DictionaryEntry类的实例对象,就代表hashTable中的一个键值对
            foreach (DictionaryEntry item in ht)
                Console.WriteLine(item.Key + "的成绩是" + item.Value);
            示例3利用枚举器来遍历
            Hashtable ht = new Hashtable();
            ht.Add("张三", 98.5f);
            ht.Add("李四", 81f);
            ht.Add("王五", 79f);
            ht.Add("赵六", 89f);
            ht.Add("沈七", 65f);
            IDictionaryEnumerator IDE = ht.GetEnumerator();
            while (IDE.MoveNext())
            {
                Console.WriteLine(IDE.Key + "的成绩是" + IDE.Value);
            }

SortedList排序列表

它可以看作是hashTableArrayList的组合,因为SortedList既可以通过键值对的方式来访问,也可以通过类似数组下标的方式来访问。

SortedList的属性

属性

描述

Capacity

获取或设置SortedList可包含的元素个数

Count

SortedList中实际包含的元素个数

IsReadOney

表示SortedList是否只读

Item

获取可设置指定键的元素的值。

IsFixedSize

表示SortedList的容量是否固定

Keys

获取一个ICollection接口的集合,其中包含了SortedList中的所有键。

Values

获取一个ICollection接口的集合,其中包含了SortedList中的所有值。

SortedList的方法

方法

描述

int Add(object key , object value)

SortedList中添加一个带有键名和键值的元素。

void clear()

移除集合中的所有元素,清空

bool ContainsKey(object Key)

判断某个键名是否包含在Hashtable

bool ContainsValue(object value)

判断某个元素的值是否包含在Hashtable

void Remove(object key)

根据元素的键名来删除第一个匹配的元素

void RemoveAt(int index)

根据下标来删除元素

int IndexOfKey(object key)

返回SotredList中指定键名的那个元素的下标序号。(下标从零开始)

int IndexOfValue(object value)

返回SotredList中指定键值第一次出现的那个元素的下标序号

IList GetKeyList()

获取SortedList中的键名的集合

IList GetValueList()

获取SortedList中的键值的集合

GetKey(i)

根据下标返回键名

示例:

            SortedList sl = new SortedList();
            sl.Add("张三", 98.5f);
            sl.Add("李四", 81f);
            sl.Add("王五", 79f);
            sl.Add("赵六", 89f);
            sl.Add("沈七", 65f);
            foreach (DictionaryEntry item in sl)
            {
                Console.WriteLine(item.Key + "的下标是" + sl.IndexOfKey(item.Key) + "的成绩是" + item.Value);
            }
            //我们可以看到,SortedList会根据键名的字符顺序来对元素进行排序
            //通过下标来遍历元素的键和值
            for (int i = 0; i < sl.Count; i++)
            {
                Console.WriteLine(sl.GetKey(i) + "的成绩" + sl.GetValueList()[i]);
            }

小练习

练习每种集合,ArrayListStackQueueHashTableSortedList的创建、添加元素、获取单个元素及遍历操作。

创建一个工具类Tool

在类中添加Name字段,并重写object类的ToString()方法,返回如下格式的字符串,“我是一个”+name+”,我能做XXX”事情。

创建一个尺子类Rule,继承自Tool类,为该类添加构造函数(name字段赋值),重写ToString()方法,返回格式与父类相似的字符串:“我是一个”+name+”,我能量长度”。

main主函数中,分别实例化三个工具类和尺子类,并将这些对象放入集合(每种集合都要测试),然后遍历显示出来。

泛型集合

非泛型集合:所有的数据存入集合之后,都会自动的进行装箱操作,转换成object类型。

泛型集合:会声明所存入数据的类型,也就是一个泛型集合中只能存入指定类型的数据。

泛型集合与非泛型集合的对应关系

泛型集合

非泛型集合

命名空间:

System.Collections.Gengeric

命名空间:

System.Collections

List<数据类型>

ArrayList

Dictionary<数据类型, 数据类型>

HashTable

Queue<数据类型>

Queue

Stack<数据类型>

Stack

SortedList<数据类型,数据类型>

SortedList

 泛型集合LIst

类似于ArrayList,不同之处是它指定了元素的类型。

语法:

List<数据类型> 集合名 = new List<数据类型>();

List<>ArrayList的属性、方法几乎是一致的。

示例1

 List<int> ListInt = new List<int>();
            ListInt.Add(14);
            ListInt.Add(28);
            ListInt.Add(50);
            foreach (int item in ListInt)
                Console.WriteLine(item);

示例2

class student
        {
            public student(string sName, int age)
            {
                this.sName = sName; this.age = age;
            }
            public string sName;
            public int age;
        }
        static void Main(string[] args)
        {
            List<student> arrL = new List<student>();
            arrL.Add(new student("张三", 18));
            arrL.Add(new student("李四", 19));
            arrL.Add(new student("王五", 20));
            arrL.Add(new student("赵六", 21));
            arrL[1].age = 88;       //用下标访问并修改元素
            arrL.RemoveAt(2);       //删除元素
            foreach (student item in arrL)
                Console.WriteLine("学生{0}的年龄是{1}", item.sName, item.age);
        }

字典Dictionary

类似于HashTable,不同之处是它指定了键名与键值的类型。

语法:

Dictionary<键名类型, 键值类型> 集合名 = new Dictionary<键名类型, 键值类型>();

Dictionary <>HashTable的属性、方法几乎是一致的。

示例:

Dictionary<string, student> sList = new Dictionary<string, student>();

            sList.Add("小白", new student("小白", 15));

            sList.Add("小黑", new student("小黑", 16));

            sList.Add("小黄", new student("小黄", 17));

            sList.Add("小红", new student("小红", 18));

            sList.Add("小强", new student("小强", 19));

            ICollection keys = sList.Keys;      //键名的集合

            foreach (string kName in keys)

                Console.WriteLine("学生姓名{0}学生年龄{1}",sList[kName].sName ,sList[kName].age);

小练习:

自行尝试并总结 队列、堆栈、排序列表的泛型版本集合的添加、遍历、修改、删除等操作,并且自行总结笔记。

将泛型集合List<>当做类似数据库一样的数据源,制作一个学生管理系统。程序启动之后,始终会弹出一个菜单,输入1:查询遍历所有学生。输入2:添加新学生。输入3:修改指定下标的学生的信息。输入4:删除指定下标的学生。学生包含(姓名、年龄、班级、地址)。

linkedList链表集合

它最大的特点是,链表中的每一个元素都好像是一个节点,每个节点存在一个节点属性以指向另一个节点。

语法

LinkedList<数据类型> 集合名 = new LinkedList<数据类型>();

示例:

 LinkedList<string> LList = new LinkedList<string>();
            LList.AddFirst("张三");       //添加到集合的最前面
            LList.AddFirst("李四");
            LList.AddLast("王五");
            LList.AddLast("李连连");       //添加到集合的最后面
            foreach (string s in LList)
            {
                Console.WriteLine(s);
            }
            //得到最后一个节点
            LinkedListNode<string> lastString = LList.Last;
            Console.WriteLine("最后一个节点是:" + lastString.Value);
            Console.WriteLine("第一个节点是:" + LList.First.Value);
            //Next属性指向下一个节点,这就是链表的特点。
            Console.WriteLine("第一个节点的后面一个是" + LList.First.Next.Value);
            Console.WriteLine("第一个节点的后面的后面是" + LList.First.Next.Next.Value);
            Console.WriteLine("最后节点的前一个是" + LList.Last.Previous.Value);
            //按索引来查找
            Console.WriteLine(LList.ElementAt<string>(1));

说明:

LinkedList<T>它是一个双向链表,它的元素指向前一个与后一个元素。

链表的优点是:如果要插入一个元素到链表之中,性能会非常快。因为你插入元素的时候,只需要修改上一个元素的Next属性和下一个元素的Previous元素的引用就可以了。(ArrayList则需要重新排列后面所有的元素 )

链表缺点是查询定位链表中间的元素中,需要较长时间。

LinkedListNode<T>节点

它表示链表中的一个节点元素,可以用来获得元素的上一个与下一个元素的引用

LinkedList常用属性与方法

Count 返回链表中的元素个数

First 链表中的第一个节点

Last 链表中的最后一个节点

AddFirst() 向链表的最前面添加一个元素

AddAfter() 向链表的指定元素之后添加一个元素

AddBefore() 向链表的指定元素之前添加一个元素

AddLast() 向链表的最后面添加一个元素

Remove()RemoveFirst()RemoveLast() 删除指定的匹配元素,或第一个、最后一个元素

Clear() 清除所有元素

Contains() 搜索一个元素是否包含在集合之中,返回truefalse

Find() 搜索一个元素是否包含在集合之中,返回元素的节点类

FindLast() 同上,区别在于它是从后向前查询

创建自己的集合类

C#中的很多类我们都可以用继承的方式来扩展它

实现自定义非泛型集合类

  

 class Program
    {
        static void Main(string[] args)
        {
            stdCollections stList = new stdCollections();
            stList.add(new student("张三", 18));
            stList.add(new student("李四", 19));
            Console.WriteLine(stList[0].name);
            Console.WriteLine(stList[1].name);
        }
    }
    class student
    {
        public student(string name, int age)
        {
            this.name = name; this.age = age;
        }
        public string name;
        public int age;
    }
    class stdCollections : System.Collections.CollectionBase
    {
        //添加Add方法实现元素添加功能
        public void add(student std)
        {
            List.Add(std);
        }
        public student this[int index]
        {
            get { return (student)List[index]; }
            set { List[index] = value; }
        }

    }

猜你喜欢

转载自www.cnblogs.com/yigegaozhongsheng/p/9452781.html