博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
对象的比较与排序(三):实现IComparable<T>和IComparer<T>泛型接口(转)
阅读量:6375 次
发布时间:2019-06-23

本文共 3411 字,大约阅读时间需要 11 分钟。

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
    }
通过上面的示例,我们可以知道,实现泛型接口,可以使代码更为简洁。

转自: 

 

转载地址:http://axjqa.baihongyu.com/

你可能感兴趣的文章
OI分类
查看>>
JAVA获取txt文件内容
查看>>
信号量的分类
查看>>
poj 2992 Divisors 整数分解
查看>>
MyEclipse 2014GA 新建 Web Project 并配置 SSH
查看>>
mysql高效获取两张表共同字段的交集数据
查看>>
一些基础密码算法的实现
查看>>
Redis高可用分布式内部交流(九)
查看>>
C#DES加密
查看>>
flex与C# Socket通信
查看>>
阿尼玛
查看>>
Jquery EasyUI的添加,修改,删除,查询等基本操作介绍
查看>>
Android于JNI调用列出的程序
查看>>
CSS3-border-radius 属性
查看>>
相似图片搜索的原理(二)(转)
查看>>
(转)Spring并发访问的线程安全性问题(高度总结)
查看>>
解决Activity启动黑屏和设置android:windowIsTranslucent不兼容activity切换动画的问题
查看>>
TextBox 英文文档
查看>>
linux系统调用函数---12
查看>>
C#开发SQLServer的Geometry和Geography存储
查看>>