来源: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>泛型接口的更多相关文章

  1. .NET/C#中对自定义对象集合进行自定义排序的方法

    一个集合可否排序,要看系统知不知道排序的规则,像内建的系统类型,int ,string,short,decimal这些,系统知道怎么排序,而如果一个集合里面放置的是自定义类型,比如自己定义了一个Car ...

  2. 复杂对象List集合的排序

    对于集合的排序,直接的有sort().间接的有借用compareTo.Comparable等,但是对于相对复杂的对象集合,还得自己实现方法来处理. 现在有这样一个思路: 第一步:从需要排序的对象集合中 ...

  3. js对象数组多字段排序

    来源:js对象数组按照多个字段进行排序 一.数组排序 Array.sort()方法可以传入一个函数作为参数,然后依据该函数的逻辑,进行数组的排序. 一般用法:(数组元素从小大进行排序) var a = ...

  4. java实现两个不同list对象合并后并排序

    工作上遇到一个要求两个不同list对象合并后并排序1.问题描述从数据库中查询两张表的当天数据,并对这两张表的数据,进行合并,然后根据时间排序.2.思路从数据库中查询到的数据放到各自list中,先遍历两 ...

  5. 程序员必知的8大排序(三)-------冒泡排序,快速排序(java实现)

    程序员必知的8大排序(一)-------直接插入排序,希尔排序(java实现) 程序员必知的8大排序(二)-------简单选择排序,堆排序(java实现) 程序员必知的8大排序(三)-------冒 ...

  6. java工具类之按对象中某属性排序

    import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang ...

  7. SDUT OJ 数据结构实验之排序三:bucket sort

    数据结构实验之排序三:bucket sort Time Limit: 250 ms Memory Limit: 65536 KiB Submit Statistic Discuss Problem D ...

  8. SDUT 3400 数据结构实验之排序三:bucket sort

    数据结构实验之排序三:bucket sort Time Limit: 150MS Memory Limit: 65536KB Submit Statistic Problem Description ...

  9. iOS--自定义相册---对象数组按照时间戳排序

    将对象按照时间戳排序,这里典型的一个例子是登录账户的排序:本地客户端可能保存了多个账户信息,在登录窗口用户可以选择已经登陆过的账户直接登录,现在的需求是要时刻让最近登陆过的账户排在前面,对于每个账户, ...

随机推荐

  1. 【Shell】运行shell出现-ash: ./test.sh: not found

    1.这是一个读取文件的脚本 #!/bin/bash for line in `cat pidtestconf` do echo $line done 因为命名的时候这边使用的是 test.sh 这边将 ...

  2. 使用waitfor 语句

    aitfor语句用于延迟后面语句的执行,可以指定延迟时间长度是具体的时间.参考下面的语句: waitfor delay ’00:01:15’ print N’到时间了’    --也可以不加N 字符串 ...

  3. module.exports和 exports 方法暴露

    在Node.js包管理时需要把方法暴露给外部文件 文件:Hello.js    Hello方法是模仿面向对象类的写法 function Hello() { var name; this.setName ...

  4. jquery 获取easyui combobox选中的值、赋值

    jquery easyui combobox 控件支持单选和多选 1.获取选中的值 $('#comboboxlist').combobox('getValue');  //单选时 $('#combob ...

  5. C# ADO.NET面向对象想法

    我认为的面向对象就是把各种问题拆分开来 逐一解决,  我想的是先是数据库,到底有什么, 然后新建一个类,类里面先是private的私有的,但是可以有无数个可以连接private的pubilc的属性 可 ...

  6. 面向对象(基础oop)之类与对象

    大家好,我叫李京阳,,很高兴认识大家,之所以我想开一个自己的博客,就是来把自己所了解的知识点通过自己的话写一下,希望被博客园的朋友们点评和一起讨论一下,也希望从博客园中多认识一些软件开发人员!现在我开 ...

  7. python学习(五)--打印错误信息

    from urllib import request #打印错误信息 except Exceptionlist = [ "http://www.baidu11.com/", &qu ...

  8. String常用操作

    常量池: 字符串一旦被初始化就不会被改变 String s="123"; s="abc"; System.out.print(s); 这段代码看上去s的值是被改 ...

  9. XML深入了解(XML JavaSprint)

    XMLHttpRequest 对象 XMLHttpRequest 对象用于在后台与服务器交换数据. XMLHttpRequest 对象是开发者的梦想,因为您能够: 在不重新加载页面的情况下更新网页 在 ...

  10. HTML <frameset> 标签

    <frameset></frameset>:框架标签,可以将页面分割,被frameset标签分割的页面,不允许使用body标签;frameset标签页面内只能出现framese ...