对象的比较与排序(三):实现IComparable<T>和IComparer<T>泛型接口
来源:http://www.cnblogs.com/eagle1986/archive/2011/12/06/2278531.html
1:比较和排序的概念
比较:两个实体类之间按>,=,<进行比较。
排序:在集合类中,对集合类中的实体进行排序。排序基于的算法基于实体类提供的比较函数。
基本型别都提供了默认的比较算法,如string提供了按字母进行比较,int提供了按整数大小进行比较。
2:IComparable和IComparer
这两个接口上一日记已经介绍过,现在用一实例再次讲解一次
当我们创建了自己的实体类,如Student,默认想要对其按照年龄进行排序,则需要为实体类实现IComparable接口。
class Student:IComparable
{
public string Name { get; set; }
public int Age { get; set; }
#region IComparable Members
public int CompareTo(object obj)
{
Student student = obj as Student;
if (Age > student.Age)
{
return 1;
}
else if (Age == student.Age)
{
return 0;
}
else
{
return -1;
}
//return Age.CompareTo(student.Age);
}
#endregion
}
PS:注意上面代码中CompareTo方法有一条注释的代码,其实本函数完全可以使用该注释代码代替,因为利用了整形的默认比较方法。此处未使用本注释代码,是为了更好的说明比较器的工作原理。
接下来写一个测试用例:
public Form1()
{
InitializeComponent();
studentList = new ArrayList();
studentList.Add(new Student() { Age = 1, Name = "a1" });
studentList.Add(new Student() { Age = 5, Name = "g1" });
studentList.Add(new Student() { Age = 4, Name = "b1" });
studentList.Add(new Student() { Age = 2, Name = "f1" });
}
ArrayList studentList;
private void button1_Click(object sender, EventArgs e)
{
studentList.Sort();
foreach (Student item in studentList)
{
this.textBox1.Text += item.Name + "----" +item.Age.ToString() + "\r\n" ;
}
}
运行结果:
a1----1
f1----2
b1----4
g1----5
OK,疑问来了。如果不想使用年龄作为比较器了,那怎么办。这个时候IComparer的作用就来了,可使用IComparer来实现一个自定义的比较器。如下:
class SortName: IComparer
{
public static IComparer Default = new PersonComparerName();
#region IComparer Members public int Compare(object x, object y)
{
Student s1 = x as Student;
Student s2 = y as Student;
return s1.Name.CompareTo(s2.Name);
} #endregion
}
这个时候,我们在排序的使用为Sort方法提供此比较器:
studentList.Sort(SortName.Default);
运行的结果是:
a1----1
b1----4
f1----2
g1----5
上一篇日记已经说过,
一般情况下,我们使用 IComparable 给出类的默认比较代码,使用其他类给出非默认的比较代码。
上面的示例,其中,我们在Student给出了默认的比较代码(实现了IComparable),所以我们可以通过 .Sort()来进行排序。
同时我们也可以给出非默认的比较代码,比如示例中的SortName (要求实现 IComparer接口),所以我们可以通过 .Sort(SortName.Default)来进行排序。
只要是实现是 IComparer接口就可以作为比较器参数丢给Sort().
3:IComparable和IComparer的泛型实现IComparable<T>和IComparer<T>
如果我们稍有经验,我们就会发现上面的代码我们使用了一个已经不建议使用的集合类ArrayList。当泛型出来后,所有非泛型集合类已经建议不尽量使用了。至于原因,从上面的代码中我们也可以看出一点端倪。
注意查看这个Compare函数,如:
public int Compare(object x, object y)
{
Student s1 = x as Student;
Student s2 = y as Student;
return s1.Name.CompareTo(s2.Name);
}
我们发现这个函数进行了装箱和拆箱。而这是会影响性能的。如果我们的集合中有成千上万个复杂的实体对象,则在排序的时候所耗费掉的性能就是客观的。而泛型的出现,就可以避免掉拆箱和装箱。
故上文代码中的ArrayList,应该换成List<T>,对应的,我们就该实现IComparable<T>和IComparer<T>。最终的代码应该像:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
studentList = new List<Student>();
studentList.Add(new Student() { Age = 1, Name = "a1" });
studentList.Add(new Student() { Age = 5, Name = "g1" });
studentList.Add(new Student() { Age = 4, Name = "b1" });
studentList.Add(new Student() { Age = 2, Name = "f1" });
}
List<Student> studentList;
private void button1_Click(object sender, EventArgs e)
{
studentList.Sort(new SortName()); foreach (Student item in studentList)
{ this.textBox1.Text += item.Name + "----" +item.Age.ToString() + "\r\n" ;
}
}
} class Student:IComparable<Student>
{
public string Name { get; set; }
public int Age { get; set; } #region IComparable<Student> Members public int CompareTo(Student other)
{
return Age.CompareTo(other.Age);
} #endregion
} class SortName: IComparer<Student>
{
#region IComparer<Student> Members public int Compare(Student x, Student y)
{
return x.Name.CompareTo(y.Name);
} #endregion
}
对象的比较与排序(三):实现IComparable<T>和IComparer<T>泛型接口的更多相关文章
- .NET/C#中对自定义对象集合进行自定义排序的方法
一个集合可否排序,要看系统知不知道排序的规则,像内建的系统类型,int ,string,short,decimal这些,系统知道怎么排序,而如果一个集合里面放置的是自定义类型,比如自己定义了一个Car ...
- 复杂对象List集合的排序
对于集合的排序,直接的有sort().间接的有借用compareTo.Comparable等,但是对于相对复杂的对象集合,还得自己实现方法来处理. 现在有这样一个思路: 第一步:从需要排序的对象集合中 ...
- js对象数组多字段排序
来源:js对象数组按照多个字段进行排序 一.数组排序 Array.sort()方法可以传入一个函数作为参数,然后依据该函数的逻辑,进行数组的排序. 一般用法:(数组元素从小大进行排序) var a = ...
- java实现两个不同list对象合并后并排序
工作上遇到一个要求两个不同list对象合并后并排序1.问题描述从数据库中查询两张表的当天数据,并对这两张表的数据,进行合并,然后根据时间排序.2.思路从数据库中查询到的数据放到各自list中,先遍历两 ...
- 程序员必知的8大排序(三)-------冒泡排序,快速排序(java实现)
程序员必知的8大排序(一)-------直接插入排序,希尔排序(java实现) 程序员必知的8大排序(二)-------简单选择排序,堆排序(java实现) 程序员必知的8大排序(三)-------冒 ...
- java工具类之按对象中某属性排序
import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang ...
- SDUT OJ 数据结构实验之排序三:bucket sort
数据结构实验之排序三:bucket sort Time Limit: 250 ms Memory Limit: 65536 KiB Submit Statistic Discuss Problem D ...
- SDUT 3400 数据结构实验之排序三:bucket sort
数据结构实验之排序三:bucket sort Time Limit: 150MS Memory Limit: 65536KB Submit Statistic Problem Description ...
- iOS--自定义相册---对象数组按照时间戳排序
将对象按照时间戳排序,这里典型的一个例子是登录账户的排序:本地客户端可能保存了多个账户信息,在登录窗口用户可以选择已经登陆过的账户直接登录,现在的需求是要时刻让最近登陆过的账户排在前面,对于每个账户, ...
随机推荐
- android studio 框架搭建:加入注解框架Annotations
参考github上的demo,新建一个project后,会有一个位于app文件夹下的局部build.gradle文件和一个位于根目录project下的全局build.gradle文件,我们要修改的是局 ...
- 【iptables】规则的试验和查看
1.存在桥接,查看桥接访客网络规则 ebtables -L 可以看到对不同的链的策略
- 获取memcache中所有数据
remap_table方法是用的一个框架写的: $gvs = $this->pageObj->get;是获取通过get方式传递过来的数据: $mem = $this->pageObj ...
- IIS7部署网站出现500.19错误(权限不足)的解决方案
错误摘要 HTTP 错误 500.19 - Internal Server Error 无法访问请求的页面,因为该页的相关配置数据无效. 详细错误信息 模块 IIS Web Core 通知 未知 处理 ...
- 《C#高效编程》读书笔记02-用运行时常量(readonly)而不是编译期常量(const)
C#有两种类型的常量:编译期常量和运行时常量.两者有截然不同的行为,使用不当的话,会造成性能问题,如果没法确定,则使用慢点,但能保证正确的运行时常量. 运行时常量使用readonly关键字声明,编译期 ...
- VS 游戏:推箱子&对战游戏
推箱子 //只做了两关 class Program { static void Main(string[] args) { ; ; ; ; ; ; ; #region 地图绘制 , , ] { { { ...
- (一)初识div+css
关于div+css,一直以来都是听其名,而不知其为何.今天看了半天的视频,终于对此略有了解,感觉挺好的,相比之前的table布局页面,div+css就是一把页面布局利器!! div全称division ...
- 【设计模式】template method(模板方法)-- 类行为型模式5.10
1.意图 子类在不改变父类的算法结构的情况下,可以重定义算法的某些特定步骤 2.动机 模板方法用一些抽象的操作定义一个算法,子类重定义这些操作以提供具体的行为:步骤的顺序定了,但实现可以调整: 3.适 ...
- sort遇到的问题
var arr = [2,10,6,9,7,8]; var arr1 = arr.sort(); var arr2 = arr.sort(function(a,b){ if (a>b){ ret ...
- 【代码笔记】Java连连看项目的实现(2)——JTable 、TableModel的使用
博客有时间就写写,所以一篇可能会拆成很多篇,写完后计划再合在一起. 首先肯定是要实现连连看的界面. 先准备连连看要的图片.. “LianLianKan”就是项目名称. 当然,如果小白看我的博客想学到什 ...