(一)泛型集合List
1)引入
数组的局限性:
- 数组元素个数是固定的,数组一旦定义,就无法改变元素总数。如果需求变化,则必须修改源码;
- 如果初始化元素总数非常大,则造成空间浪费;
集合的特点:
- 根据需要动态增加元素个数,没有限制;
2)泛型集合
1. List泛型集合的特点:
- 表示泛型,T是Type的简写,表示当前不确定具体类型;
- 可以根据用户的实际需要,确定当前集合需要存放的数据类型;但是,一旦确定不可改变;
2. List泛型集合的存储结构:
3. 泛型集合的要求:
- 使用泛型集合只能添加一种类型的数据,数据取出后 无需强制转换;
4. List使用之前的准备工作:
- 引入命名空间:System.Collections.Generic;
- 确定存储类型:
List<Student> students = new List<Student>();
5. 常用方法:
- 添加元素:
Add(<T>)
- 删除元素:
RemoveAt(索引)
6. 常用属性:
元素个数:Count
7. 遍历集合:
foreach (Student stu in students)
{
Console.WriteLine(stu.StudentName);
}
举例:
namespace Demo
{
/// <summary>
/// 学生类
/// </summary>
class Student
{
public Student() { }
public Student(int stuId, string stuName)
{
this.StudentId = stuId;
this.StudentName = stuName;
}
public int StudentId { get; set; }
public string StudentName { get; set; }
public int Age { get; set; }
}
}
using System;
using System.Collections.Generic;
namespace Demo
{
class Program
{
static void Main(string[] args)
{
//创建学员对象
Student objStu1 = new Student(1001, "小王");
Student objStu2 = new Student(1002, "小张");
Student objStu3 = new Student(1003, "小李");
Student objStu4 = new Student(1004, "小赵");
//创建list集合
List<Student> StuList = new List<Student>();
StuList.Add(objStu1);
StuList.Add(objStu2);
StuList.Add(objStu3);
StuList.Add(objStu4);
StuList.Add(new Student()
{
StudentId = 1006,
StudentName = "小黑"
});
//获取元素个数
Console.WriteLine("元素总数:{0}", StuList.Count);
//删除一个元素
StuList.Remove(objStu1); //删除一个对象
StuList.RemoveAt(1); //删除位置为1的元素
//插入一个对象
StuList.Insert(0, new Student(1005, "小白"));
//遍历集合
foreach (Student item in StuList)
{
Console.WriteLine(item.StudentName + "\t" + item.StudentId);
}
}
}
}
8. 集合初始化器:
创建集合对象的时候直接初始化,非常类似于数组;
(二)泛型集合Dictionary<K, V>的使用
1)关于Dictionary<K, V>泛型集合
- Dictionary<K,V> 通常称之为字典,<K, V>约束集合中元素类型;
- 编译时,检查类型约束,无需装箱拆箱操作,与哈希表操作类似;
Dictionary<K, V>的存储结构
举例:
namespace Demo
{
/// <summary>
/// 学生类
/// </summary>
class Student
{
public Student() { }
public Student(int stuId, string stuName)
{
this.StudentId = stuId;
this.StudentName = stuName;
}
public int StudentId { get; set; }
public string StudentName { get; set; }
public int Age { get; set; }
}
}
using System;
using System.Collections.Generic;
namespace Demo
{
class Program
{
static void Main(string[] args)
{
//创建学员对象
Student objStu1 = new Student(1001, "小王");
Student objStu2 = new Student(1002, "小张");
Student objStu3 = new Student(1003, "小李");
Student objStu4 = new Student(1004, "小赵");
//创建Dictionary泛型集合
Dictionary<string, Student> stus = new Dictionary<string, Student>();
stus.Add("小王", objStu1);
stus.Add("小张", objStu2);
//注意这里使用的是中括号
Console.WriteLine(stus["小王"].StudentId);
//Dictionary泛型集合遍历(两种方式)
//第一种
foreach (string key in stus.Keys)
{
Console.WriteLine(key);
}
//第二种
foreach (Student item in stus.Values)
{
Console.WriteLine(item.StudentName + "\t" + item.StudentId);
}
}
}
}
(三)集合中对象的排序
1)基本数据类型的排序
基本数据类型可以直接进行排序;使用Sort()方法,对于字符串元素,默认按照字母、拼音升序排列;
注意:使用Reverse()方法实现反转;
List<string> list = new List<string>()
{
"小王","小张","小孙","小李","小赵"
};
foreach (string item in list)
{
Console.WriteLine(item);
}
Console.WriteLine("--------排序后--------");
list.Sort(); //排序
list.Reverse(); //排序后反转
foreach(string item in list)
{
Console.WriteLine(item);
}
2)对象的排序
集合不能简单的使用Sort()排序;
原因:找不到排序的属性;
注意:一个类前面加 “I” 表示这个类的接口;
将需要排序的对象实现泛型接口 IComparable< T> 按照学号排序
注意:return this.StuId.CompareTo(other.StuId)实现升序排序(按照学号)
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
namespace Demo
{
/// <summary>
/// 学生类
/// </summary>
class Student:IComparable<Student>
{
public Student() {}
public Student(int stuId, string stuName)
{
this.StudentId = stuId;
this.StudentName = stuName;
}
public int StudentId { get; set; }
public string StudentName { get; set; }
public int Age { get; set; }
/// <summary>
/// 接口的实现方法
/// </summary>
/// <param name="other"></param>
/// <returns></returns>
public int CompareTo([AllowNull] Student other)
{
//下面代码实现升序排序;this和other交换位置实现降序
return this.StudentId.CompareTo(other.StudentId);
}
}
}
using System;
using System.Collections.Generic;
namespace Demo
{
class Program
{
static void Main(string[] args)
{
Student objStu1 = new Student(1001, "小王");
Student objStu2 = new Student(1002, "小张");
Student objStu3 = new Student(1003, "小赵");
Student objStu4 = new Student(1004, "小孙 ");
List<Student> Stus = new List<Student>() { objStu1, objStu2, objStu3, objStu4 };
Stus.Sort();
foreach (Student item in Stus)
{
Console.WriteLine(item.StudentName);
}
}
}
}
3)对象排序------根据需要添加排序方法(动态)
默认排序只能有一种
接口本身也是一种数据类型;类也是数据类型;
注意:
- 默认排序只能有一种;
- 根据需要添加排序类,C#中允许一个类文件对应若干具体的类;
- 需要几种排序就增加几个排序类;
- 当需要多种排序的时候可以不使用默认排序;下面的类排序完全可以替代默认排序;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
namespace Demo
{
/// <summary>
/// 学生类
/// </summary>
class Student:IComparable<Student> //默认排序只能有一种
{
public Student() {}
public Student(int stuId, string stuName)
{
this.StudentId = stuId;
this.StudentName = stuName;
}
public int StudentId { get; set; }
public string StudentName { get; set; }
public int Age { get; set; }
/// <summary>
/// 接口的实现方法
/// </summary>
/// <param name="other"></param>
/// <returns></returns>
public int CompareTo([AllowNull] Student other)
{
//下面代码实现升序排序;this和other交换位置实现降序
return this.StudentId.CompareTo(other.StudentId);
}
}
//根据需要添加排序类,C#中允许一个类文件对应若干具体的类
//需要几种排序就增加几个排序类
//添加排序类并且分别实现排序接口
class StuNameASC : IComparer<Student> //实现这个接口
{
public int Compare([AllowNull] Student x, [AllowNull] Student y)
{
return x.StudentName.CompareTo(y.StudentName);
}
}
class StuNameDESC : IComparer<Student>
{
public int Compare([AllowNull] Student x, [AllowNull] Student y)
{
return y.StudentName.CompareTo(x.StudentName);
}
}
class AgeASC : IComparer<Student>
{
public int Compare([AllowNull] Student x, [AllowNull] Student y)
{
return x.Age.CompareTo(y.Age);
}
}
class AgeDESC : IComparer<Student>
{
public int Compare([AllowNull] Student x, [AllowNull] Student y)
{
return y.Age.CompareTo(x.Age);
}
}
}
using System;
using System.Collections.Generic;
namespace Demo
{
class Program
{
static void Main(string[] args)
{
Student objStu1 = new Student() { StudentId = 1001, StudentName = "小李", Age = 20 };
Student objStu2 = new Student() { StudentId = 1002, StudentName = "张红", Age = 27 };
Student objStu3 = new Student() { StudentId = 1003, StudentName = "汪洋", Age = 22 };
Student objStu4 = new Student() { StudentId = 1004, StudentName = "郝鑫", Age = 17 };
List<Student> Stus = new List<Student>() { objStu1, objStu2, objStu3, objStu4 };
//默认排序
Stus.Sort();
Console.WriteLine("-------默认排序--------");
foreach (Student item in Stus)
{
Console.WriteLine(item.StudentId + "\t" + item.StudentName + "\t"+ item.Age);
}
Console.WriteLine("-------按照姓名升序-------");
Stus.Sort(new StuNameASC()); //里面必须是接口实现类的对象
foreach (Student item in Stus)
{
Console.WriteLine(item.StudentId + "\t" + item.StudentName + "\t" + item.Age);
}
Console.WriteLine("-------按照姓名降序-------");
Stus.Sort(new StuNameDESC());
foreach (Student item in Stus)
{
Console.WriteLine(item.StudentId + "\t" + item.StudentName + "\t" + item.Age);
}
Console.WriteLine("-------按照年龄升序-------");
Stus.Sort(new AgeASC());
foreach (Student item in Stus)
{
Console.WriteLine(item.StudentId + "\t" + item.StudentName + "\t" + item.Age);
}
Console.WriteLine("-------按照年龄降序-------");
Stus.Sort(new AgeDESC());
foreach (Student item in Stus)
{
Console.WriteLine(item.StudentId + "\t" + item.StudentName + "\t" + item.Age);
}
}
}
}
其实上面是多态的一种应用;多态有两种实现方式
- 基于继承;(1)将父类作为方法的参数,实际上传递的是父类的子类对象;(2)将父类类型作为方法的返回值;
- 基于接口;(1)将接口作为方法的参数,传入接口的实现类对象;(2)将接口作为返回值;
4)Sort方法总结
List集合的Sort方法总共有四种:
- Sort() :使用默认比较器IComparable<> 排序对象;【无参数】
- Sort(ICompare<> compare) : 将实现比较器接口的对象作为参数;【典型多态形式】
…
集合排序总结:
- 如果是基本数据类型元素,可以直接进行排序;
- 如果是对象类型元素:
- 当排序只有一种的时候,可以使用默认比较器IComparable<>,在类中实现接口即可;
- 当需要多种排序的时候,需要添加对应排序类,并给每一个排序类实现比较器接口ICompare<> 来完成不同排序方法;