第六节复习
泛型和非泛型集合的区别
通常情况下,建议您使用泛型集合,因为这样可以获得类型安全的直接优点而不需要从基集合类型派生并实现类型特定的成员。此外,如果集合元素为值类型,泛型集合类型的性能通常优于对应的非泛型集合类型(并优于从非泛型基集合类型派生的类型),因为使用泛型时不必对元素进行装箱。
下面的泛型类型对应于现有的集合类型:
-
List 是对应于 ArrayList 的泛型类。
-
Dictionary 是对应于 Hashtable 的泛型类。
-
Collection 是对应于 CollectionBase 的泛型类。Collection 可以用作基类,但是与 CollectionBase 不同的是它不是抽象的,因而更易于使用。
-
ReadOnlyCollection 是对应于 ReadOnlyCollectionBase 的泛型类。ReadOnlyCollection 不是抽象的,它具有一个构造函数,该构造函数使其更易于将现有的 List 公开为只读集合。
-
Queue、Stack 和 SortedList 泛型类分别对应于与其同名的非泛型类。
class Program { static void Main(string[] args) { //ArrayList list = new ArrayList() { 3, 2, 1, 6, 789, 13, 54 }; //list.Sort(); //for (int i = 0; i < list.Count; i++) //{ // Console.WriteLine(list[i]); //} //Console.ReadKey(); //ArrayList list = new ArrayList() { //new Person(){ Name="Zhangsan", Age=17}, //new Person(){ Name="Lisi", Age=15}, //new Person(){ Name="ZhaoLiu", Age=18}, //new Person(){ Name="WangQi", Age=27} //}; //list.Sort(); //MyArrayList mylist = new MyArrayList(); //mylist.Add(10); //mylist.Add(9); //mylist.Add(5); //mylist.Add(8); //mylist.Add(6); //MyArrayList mylist = new MyArrayList(); //mylist.Add("yushangyong"); //mylist.Add("gaowenmi"); //mylist.Add("yanliupan"); //mylist.Add("lirende"); //mylist.Add("lijingjing"); //MyArrayList mylist = new MyArrayList(); //mylist.Add(new Person() { Name = "yushangyong", Age = 10 }); //mylist.Add(new Person() { Name = "gaowenmi", Age = 13 }); //mylist.Add(new Person() { Name = "yanliupan", Age = 20 }); //mylist.Add(new Person() { Name = "lirende", Age = 7 }); //mylist.Add(new Person() { Name = "lijingjing", Age = 6 }); //mylist.Sort(new PersonSortByNameLengthDesc()); //for (int i = 0; i < mylist.Count; i++) //{ // Console.WriteLine(((Person)mylist[i]).Name); //} //List<string> list = new List<string>(); //list.Sort(); //Console.ReadKey(); //string msg = "赵"; //string msg1 = "钱"; //int n = msg.CompareTo(msg1); //Console.WriteLine(n); //Console.WriteLine((int)msg[0] + " " + (int)msg1[0]); //Console.Read(); } } public class PersonSortByNameLengthDesc : IComparer { #region IComparer 成员 public int Compare(object x, object y) { Person p1 = x as Person; Person p2 = y as Person; return p2.Name.Length - p1.Name.Length; } #endregion } class Person { public string Name { get; set; } public int Age { get; set; } } //class Person : IComparable //{ // public string Name // { // get; // set; // } // public int Age // { // get; // set; // } // #region IComparable 成员 // public int CompareTo(object obj) // { // Person p1 = obj as Person; // return this.Age - p1.Age; // } // #endregion //} class MyArrayList { private ArrayList _list = new ArrayList(); public void Add(object obj) { _list.Add(obj); } public object this[int index] { get { return _list[index]; } } public void Sort() { //自己写一个冒泡排序法,对_list中的内容进行排序 for (int i = 0; i < _list.Count - 1; i++) { for (int j = _list.Count - 1; j > i; j--) { #region 写死了,只能对整型排序 //if ((int)_list[j] < (int)_list[j - 1]) //{ // int tmp = (int)_list[j]; // _list[j] = _list[j - 1]; // _list[j - 1] = tmp; //} #endregion IComparable obj1 = _list[j] as IComparable; IComparable obj2 = _list[j - 1] as IComparable; //判断集合中的元素是否可以成功转换为IComparable接口类型 if (obj1 != null && obj2 != null) { //无论集合中存储的是什么类型,这里都可以通过CompareTo来实现比较大小 if (obj1.CompareTo(obj2) < 0) { object tmp = _list[j]; _list[j] = _list[j - 1]; _list[j - 1] = tmp; } } else { throw new ArgumentException(); } } } } //参数是一个比较器,需要自己写一个类来实现。 public void Sort(IComparer comparer) { //自己写一个冒泡排序法,对_list中的内容进行排序 for (int i = 0; i < _list.Count - 1; i++) { for (int j = _list.Count - 1; j > i; j--) { //if (_list[j] < _list[j - 1]) //{ //} //比较两个元素大小 if (comparer.Compare(_list[j], _list[j - 1]) < 0) { object tmp = _list[j]; _list[j] = _list[j - 1]; _list[j - 1] = tmp; } } } } //remove public void Remove(object obj) { _list.Remove(obj); } public int Count { get { return _list.Count; } } }
习题练习
class Program { static void Main(string[] args) { #region 案例:把分拣奇偶数的程序用泛型实现。List<int> //string msg = "2 7 8 3 22 9 5 11"; //string[] nums = msg.Split(' '); //List<string> listOdd = new List<string>(); //List<string> listEvent = new List<string>(); //for (int i = 0; i < nums.Length; i++) //{ // if (Convert.ToInt32(nums[i]) % 2 == 0) // { // listEvent.Add(nums[i]); // } // else // { // listOdd.Add(nums[i]); // } //} //listOdd.AddRange(listEvent); //string str = string.Join(" ", listOdd.ToArray()); //Console.WriteLine(str); //Console.Read(); #endregion #region 练习1:将int数组中的奇数放到一个新的int数组中返回。 //int[] arrInt = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; //List<int> list = new List<int>(); //for (int i = 0; i < arrInt.Length; i++) //{ // if (arrInt[i] % 2 != 0) // { // list.Add(arrInt[i]); // } //} //int[] arrOddInt = list.ToArray(); //for (int i = 0; i < arrOddInt.Length; i++) //{ // Console.WriteLine(arrOddInt[i]); //} //Console.ReadKey(); #endregion #region 练习2:从一个整数的List<int>中取出最大数(找最大值)。别用max方法。 //List<int> list = new List<int>() { 1, 2, 3, 4, 54, 12, 23, 6, 33 }; //int max = list[0]; //for (int i = 1; i < list.Count; i++) //{ // if (list[i] > max) // { // max = list[i]; // } //} //Console.WriteLine(max); //Console.ReadKey(); #endregion #region 练习:把123转换为:壹贰叁。Dictionary<char,char> //string str = "1壹 2贰 3叁 4肆 5伍 6陆 7柒 8捌 9玖 0零"; //Dictionary<char, char> _dict = new Dictionary<char, char>(); //string[] parts = str.Split(' '); //for (int i = 0; i < parts.Length; i++) //{ // _dict.Add(parts[i][0], parts[i][1]); //} //while (true) //{ // Console.WriteLine("请输入阿拉伯数字:"); // string number = Console.ReadLine(); // char[] chs = number.ToCharArray(); // for (int i = 0; i < chs.Length; i++) // { // if (_dict.ContainsKey(chs[i])) // { // chs[i] = _dict[chs[i]]; // } // } // Console.WriteLine(new string(chs)); //} #endregion #region 计算字符串中每种字母出现的次数(面试题)。 “Welcome ,to Chinaworld”,不区分大小写,打印“W2”“e 2”“o 3”…… //string msg = "Welcome ,to Chinaworld"; //msg = msg.ToLower(); //Dictionary<char, int> dict = new Dictionary<char, int>(); //for (int i = 0; i < msg.Length; i++) //{ // //只考虑字母 // if (char.IsLetter(msg[i])) // { // if (!dict.ContainsKey(msg[i])) // { // dict.Add(msg[i], 1); // } // else // { // dict[msg[i]]++; // } // } //} ////遍历dict集合 //foreach (KeyValuePair<char, int> kv in dict) //{ // Console.WriteLine(kv.Key + " 出现了 {0}次。", kv.Value); //} //Console.ReadLine(); #endregion //Console.WriteLine(char.IsLetter('中')); //Console.ReadLine(); } }
简繁体转换
public partial class Form1 : Form { public Form1() { InitializeComponent(); } Dictionary<char, char> dict = new Dictionary<char, char>(); private void Form1_Load(object sender, EventArgs e) { //初始化集合 //1.读取文本文件中的每一行 string[] lines = File.ReadAllLines("简体-繁体.txt", Encoding.Default); //2.遍历每一行数据Split分割,把简体作为键,把繁体作为值 foreach (string item in lines) { string[] parts = item.Split('='); dict.Add(parts[0][0], parts[1][0]); } } private void button1_Click(object sender, EventArgs e) { //1,获取用户输入的文本 string userInput = textBox1.Text.Trim(); //循环每个字符,找到对应的繁体并且拼接 StringBuilder sbFanti = new StringBuilder(); for (int i = 0; i < userInput.Length; i++) { if (dict.ContainsKey(userInput[i])) { sbFanti.Append(dict[userInput[i]]); } else { sbFanti.Append(userInput[i]); } } textBox2.Text = sbFanti.ToString(); } private void button2_Click(object sender, EventArgs e) { //1.构建英汉词典集合(Dictionary) Dictionary<string, string> dictEnCn = new Dictionary<string, string>(); //2.获取用户输入的英文单词 string[] lines = File.ReadAllLines("英汉词典TXT格式.txt", Encoding.Default); //2.1初始化词典集合 foreach (string line in lines) { string[] parts = line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (dictEnCn.ContainsKey(parts[0])) { dictEnCn[parts[0]] += Environment.NewLine + parts[1]; } else { dictEnCn.Add(parts[0], parts[1]); } } //3.根据英文单词查找对应的汉语解释 //获取用户输入的英文单词 string userInput = textBox1.Text.Trim(); if (!dictEnCn.ContainsKey(userInput)) { textBox2.Text = "对不起,词典中没有该词。"; } else { textBox2.Text = dictEnCn[userInput]; } //4.显示到文本框中 } }
效果图
日期转换
class Program { static void Main(string[] args) { #region 案例:编写一个函数进行日期转换,将输入的中文日期转换为阿拉伯数字日期,比如:二零一二年十二月月二十一日要转换为2012-12-21。(处理“十”的问题:1.*月十日;2.*月十三日;3.*月二十三日;4.*月三十日;)4中情况对“十”的不同翻译。1→10;2→1;3→不翻译;4→0【年部分不可能出现’十’,都出现在了月与日部分。】 //二零一二年十二月二十一日(2012年12月21日)、二零零九年七月九日、二零一零年十月二十四日、二零一零年十月二十日 while (true) { Console.WriteLine("请输入一个中文日期"); string date = Console.ReadLine(); date = ConvertChineseDateToNormalDate(date); Console.WriteLine(date); } #endregion } //把中文日期转换为数字日期 private static string ConvertChineseDateToNormalDate(string date) { //1.构建一个 中文<==>数字 一一对应的一个键值对集合 Dictionary<char, char> dict = new Dictionary<char, char>(); string ziDian = "零0 一1 二2 三3 四4 五5 六6 七7 八8 九9"; string[] parts = ziDian.Split(' '); for (int i = 0; i < parts.Length; i++) { dict.Add(parts[i][0], parts[i][1]); } StringBuilder sbDate = new StringBuilder(); //遍历日期中的每个字符,对于每个字符进行转换,如果遇到该字符是'十',则做特殊处理,否则,直接将中文替换为数字 //2.遍历用户输入的日期中的每个字符,进行转换 for (int i = 0; i < date.Length; i++) { if (dict.ContainsKey(date[i])) { sbDate.Append(dict[date[i]]); } else if (date[i] == '十') { //如果当前遍历的字符是'十',则做一些特殊处理 //处理“十”的问题:1.*月十日;2.*月十三日;3.*月二十三日;4.*月三十日; if (!dict.ContainsKey(date[i - 1]) && !dict.ContainsKey(date[i + 1])) { sbDate.Append("10"); } else if (!dict.ContainsKey(date[i - 1]) && dict.ContainsKey(date[i + 1])) { sbDate.Append("1"); } else if (dict.ContainsKey(date[i - 1]) && dict.ContainsKey(date[i + 1])) { } else if (dict.ContainsKey(date[i - 1]) && !dict.ContainsKey(date[i + 1])) { sbDate.Append("0"); } } else { sbDate.Append(date[i]); } } return sbDate.ToString(); } }
装箱拆箱
class Program { static void Main(string[] args) { #region 装箱与拆箱 //装箱:把值类型转换为引用类型,就叫装箱。 //int n = 10; //double d = n; //没有发生装箱,因为都是值类型 //Console.WriteLine(d); //int n = 10; //string s = n.ToString();//这个不是装箱。string与int是完全不同的两种类型,没有父子类关系,所以不可能发生装箱和拆箱,因为本身就不具备类型直接转换的功能。 //Console.WriteLine(s); //int n = 10; ////n是int类型,int就是Int32,而Int32是一个结构继承字System.ValueType而该类又继承自Object,所以int类型与object类型具有子父类关系,所以可以发生类型 //object o = n;//这里发生了一次装箱。 //Console.WriteLine(o); //Person p = new Person(); //object o = p;//装箱了吗?都是引用类型,没有装箱。 //Console.WriteLine(o); //拆箱:把引用类型转换为值类型,就叫拆箱。 //int n = 10; //double d = n; //int m = (int)d;//拆箱了吗?没有,因为都是值类型。 //object o = 10;//发生了一次装箱 //int n = (int)o;//拆箱了 //double d = 90; //object o = d;//装箱 //int n = (int)o;//拆箱,但是拆箱有问题,装箱的时候使用的什么数据类型,拆箱的时候必须还是使用对应的数据类型拆箱。 //Console.WriteLine(n); //Console.ReadLine(); #endregion #region 装箱与拆箱的效率问题 //ArrayList arrayList = new ArrayList(); //Stopwatch watch = new Stopwatch(); //watch.Start(); //for (int i = 0; i < 10000000; i++) //{ // arrayList.Add(i); //} //watch.Stop(); //Console.WriteLine(watch.ElapsedMilliseconds); //Console.ReadLine(); //List<int> list = new List<int>(); //Stopwatch watch = new Stopwatch(); //watch.Start(); //for (int i = 0; i < 10000000; i++) //{ // list.Add(i); //} //watch.Stop(); //Console.WriteLine(watch.ElapsedMilliseconds); //Console.ReadLine(); #endregion #region 装箱拆箱案例 //int n = 10, m = 100; //string s1 = "58"; //string s2 = "200"; //string s = n + m + s1 + s2; //只发生了一次装箱,先把n与m相加,然后再与字符串拼接,调用Concat()方法。 ////string s = n + s1 + m + s2;//这里发生了两次装箱 //int r = int.Parse(s); //Console.WriteLine(r);//如果遇到函数重载有对应的类型则也不发生装箱。 ////Console.WriteLine("最后结果是:{0}", r);// 这里调用了object参数的重载所以这里也装箱了 //Console.ReadLine(); int n = 10; //object o = n; IComparable com = n; int m = (int)com; #endregion } }
文件路径 using System.IO;
{ static void Main(string[] args) { #region Path 操作文件路径的类 文件路径→字符串 ////Path类就是对字符串的操作,与实际的文件没有任何关系 //string path = @"C:UsersAdministratorDesktop123.txt"; ////获取文件名,带后缀 //string filename = Path.GetFileName(path);//123.txt //Console.WriteLine(filename); ////获取文件名不带后缀 //string fname = Path.GetFileNameWithoutExtension(path);//123 //Console.WriteLine(fname); ////只获取文件后缀 //string ext = Path.GetExtension(path);//.txt //Console.WriteLine(ext); ////截取文件的路径部分,不带文件名、 //string filePath = Path.GetDirectoryName(path);//C:UsersAdministratorDesktop //Console.WriteLine(filePath); //////只是把字符串中的文件的路径改了,与磁盘上的文件无关。 //string newpath = Path.ChangeExtension(path, ".exe");//C:UsersAdministratorDesktop123.exe //Console.WriteLine(newpath); //string s1 = @"c:abcxyzaa"; //string s2 = "abc.avi"; ////连接两个路径。 //string full = Path.Combine(s1, s2); //s1 + s2; //Console.WriteLine(full);//c:abcxyzaaabc.avi //获取当前的临时目录的路径。 //string path = Path.GetTempPath();//C:\UsersAdministratorAppDataLocalTemp //Console.WriteLine(path); //string tmpName = Path.GetTempFileName();//C:\UsersAdministratorAppDataLocalTemp mp52F1.tmp //Console.WriteLine(tmpName); //Console.ReadLine(); Console.ReadLine(); #endregion } }
Directory类操作文件夹
class Program { static void Main(string[] args) { ////Directory.GetDirectories(); ////Directory.GetFiles(); ////Directory.Exists是判断指定的目录是否存在,不会验证文件是否存在 //bool b = Directory.Exists(@"C:UsersAdministratorDesktopaa"); //Console.WriteLine(b); //if (Directory.Exists(@"C:UsersAdministratorDesktopaa")) //{ // //只能删除空目录 // //Directory.Delete(@"C:UsersAdministratorDesktopaa"); // //可以删除整个目录,连同子文件、子文件夹都删除了。 // Directory.Delete(@"C:UsersAdministratorDesktopaa", true); // Console.WriteLine("删除成功"); //} //else //{ // Console.WriteLine("没有该路径"); //} //////File.Exists();//验证指定的文件是否存在 //Console.ReadLine(); string path = @"F:酩樽汇录像"; //读取指定目录下的所有子目录 //string[] dirs = Directory.GetDirectories(path); string[] dirs = Directory.GetDirectories(path, "*酩樽汇*", SearchOption.AllDirectories); foreach (var item in dirs) { Console.WriteLine(item); } Console.WriteLine("============================="); //获取指定目录下的所有的子文件 string[] files = Directory.GetFiles(path, "*酩樽汇*", SearchOption.AllDirectories); foreach (string item in files) { Console.WriteLine(item); } Console.ReadLine(); } }
把目录递归加载到TreeView
设计窗体
public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button2_Click(object sender, EventArgs e) { //清空所有节点 treeView1.Nodes.Clear(); } private void button3_Click(object sender, EventArgs e) { //增加一个根节点 string userInput = textBox2.Text.Trim(); //把userInput内容加到TreeView的根节点中 //Add()方法的返回值就是刚刚增加的节点 TreeNode node = treeView1.Nodes.Add(userInput); node.BackColor = Color.Yellow; } private void button4_Click(object sender, EventArgs e) { //1.判断用户是否有选中节点 TreeNode node = treeView1.SelectedNode; if (node != null)//证明有选中节点 { //2.获取用户输入的节点名称, string name = textBox2.Text.Trim(); node.Nodes.Add(name); //3.在选中的节点下增加子节点 } else { MessageBox.Show("请先选择节点!"); } } private void button5_Click(object sender, EventArgs e) { if (treeView1.SelectedNode != null) { MessageBox.Show(treeView1.SelectedNode.Text); } } private void button6_Click(object sender, EventArgs e) { //删除选中节点 if (treeView1.SelectedNode != null) { //删除当前选中节点,“自杀” treeView1.SelectedNode.Remove(); } } }
练习:
代码如下:
public partial class Form2 : Form { public Form2() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { #region 只加载子目录 ////1.获取用户输入的路径path //string path = textBox1.Text.Trim(); ////2.获取该路径下的所有的子文件夹 ////2.1把这些所有文件夹加载到TreeView上 //string[] dirs = Directory.GetDirectories(path); ////遍历所有的文件夹的路径加载到TreeView上 //foreach (string item in dirs) //{ // treeView1.Nodes.Add(Path.GetFileName(item)); //} ////3.获取指定目录下的所有的子文件 ////3.1把这些文件加载到TreeView上 //string[] files = Directory.GetFiles(path); //foreach (string item in files) //{ // treeView1.Nodes.Add(Path.GetFileName(item)); //} #endregion //获取用户输入的一个路径 string path = textBox1.Text.Trim(); //调用该方法实现将指定路径下的子文件与子目录按照层次结构加载到TreeView LoadFilesAndDirectoriesToTree(path, treeView1.Nodes); //treeView1.Nodes //TreeNodeCollection c = treeView1.Nodes; //LoadData(path, c); } private void LoadFilesAndDirectoriesToTree(string path, TreeNodeCollection treeNodeCollection) { //1.先根据路径获取所有的子文件和子文件夹 string[] files = Directory.GetFiles(path); string[] dirs = Directory.GetDirectories(path); //2.把所有的子文件与子目录加到TreeView上。 foreach (string item in files) { //把每一个子文件加到TreeView上 treeNodeCollection.Add(Path.GetFileName(item)); } //文件夹 foreach (string item in dirs) { TreeNode node = treeNodeCollection.Add(Path.GetFileName(item)); //由于目录,可能下面还存在子目录,所以这时要对每个目录再次进行获取子目录与子文件的操作 //这里进行了递归 LoadFilesAndDirectoriesToTree(item, node.Nodes); } } }
Directory:
public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { for (int i = 0; i < 20; i++) { Directory.CreateDirectory(@"c:aaaxxxb" + i); File.Create(@"c:aaaxxxb" + i + ".txt"); } MessageBox.Show("ok"); } private void button2_Click(object sender, EventArgs e) { //剪切 //Directory.Move(@"c:aaa", @"c:xaaa"); //重命名 Directory.Move(@"c:x", @"c:xyz"); MessageBox.Show("ok"); } }
资料管理器:
public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { // 窗体加载事件 //1.获取路径 string path = "demo"; //2.调用方法递归加载 LoadData(path, treeView1.Nodes); } private void LoadData(string path, TreeNodeCollection treeNodeCollection) { //1.获取path下的所有的目录与文件 string[] files = Directory.GetFiles(path, "*.txt"); string[] dirs = Directory.GetDirectories(path); //遍历加载到TreeView上 //文件 foreach (string item in files) { treeNodeCollection.Add(Path.GetFileName(item)); } //目录 foreach (string item in dirs) { TreeNode node = treeNodeCollection.Add(Path.GetFileName(item)); LoadData(item, node.Nodes); } } }