zoukankan      html  css  js  c++  java
  • 创建对象时需要考虑是否实现比较器

    1、基础

      有对象的地方,一般都会存在比较。在此根据一个Salary列表实现对象比较的例子。Salary类需要实现接口IComparable。

    class Salary:IComparable
    {
        public string Name { get; set; }
        public int BaseSalary { get; set; }
        public int Bonus { get; set; }
    
        public int CompareTo(object obj)
        {
            Salary salary = obj is Salary ? obj as Salary : null;
            if(salary==null)
            {
                throw new Exception("类型不同,无法比较");
            }
            if(BaseSalary>salary.BaseSalary)
            {
                return 1;
            }
            else if(BaseSalary==salary.BaseSalary)
            {
                return 0;
            }
            else
            {
                return -1;
            }
            //以上代码可有以下代码代替,使用整型默认比较方法
            //return BaseSalary.CompareTo(salary.BaseSalary);
        }
    }

      实现接口IComparable后,可以根据BaseSalary对Salary集合对象排序。在Main函数中代码如下:

    public static void Main()
    {
        ArrayList companySalary = new ArrayList();
        companySalary.Add(new Salary() { Name = "Mike", BaseSalary = 3000,Bonus=1000 });
        companySalary.Add(new Salary() { Name = "Rose", BaseSalary = 2000, Bonus = 6000 });
        companySalary.Add(new Salary() { Name = "Tom", BaseSalary = 5000, Bonus = 5000 });
        companySalary.Add(new Salary() { Name = "Jeffry", BaseSalary = 1000, Bonus = 2000 });
        companySalary.Add(new Salary() { Name = "Steve", BaseSalary = 4500, Bonus = 1900 });
        companySalary.Sort();
        foreach (Salary salary in companySalary)
        {
            Console.WriteLine("{0}	 BaseSalary: {1}	Bonus: {2}", salary.Name, salary.BaseSalary,salary.Bonus);
        }
    }

      但是,此处实现相当于比较局限,局限与只能使用BaseSalary排序,不能使用其他方式排序。如果使用Bonus进行排序,就需要改变源码。接口IComparer的作用可以避免这类问题。

    2、IComparer接口

      使用IComparer接口实现一个自定义比较器:

    class BonusComparer : IComparer
    {
         int IComparer.Compare(object x, object y)
        {
            Salary salary1 = x is Salary ? x as Salary : null;
            Salary salary2 = y is Salary ? y as Salary : null;
            return salary1.Bonus.CompareTo(salary2.Bonus);
        }
    }

      在主控端调用时排序时,需要在Sort方法中传入一个实现了IComparer接口的比较器对象:companySalary.Sort(new BonusComparer())。以此实现可以根据需要,实现多种比较。

    3、泛型实现

      在前面,使用了性能不高的ArrayList类。在泛型出来之后,需要尽量使用泛型集合。在CompareTo和Compare和函数中,需要对对象进行转型,比较影响性能,尤其是对大型集合进行排序时,性能影响非常明显。而泛型的出现,可以避免运行时的转型。因此,上面的代码全部更换为泛型类型:

    class Program
    {
        public static void Main()
        {
            List<Salary> companySalary = new List<Salary>();
            companySalary.Add(new Salary() { Name = "Mike", BaseSalary = 3000, Bonus = 1000 });
            companySalary.Add(new Salary() { Name = "Rose", BaseSalary = 2000, Bonus = 6000 });
            companySalary.Add(new Salary() { Name = "Tom", BaseSalary = 5000, Bonus = 5000 });
            companySalary.Add(new Salary() { Name = "Jeffry", BaseSalary = 1000, Bonus = 2000 });
            companySalary.Add(new Salary() { Name = "Steve", BaseSalary = 4500, Bonus = 1900 });
            companySalary.Sort();
            foreach (Salary salary in companySalary)
            {
                Console.WriteLine("{0}	 BaseSalary: {1}	Bonus: {2}", salary.Name, salary.BaseSalary, salary.Bonus);
            }
            companySalary.Sort(new BonusComparer());//提供一个默认比较器
            foreach (Salary salary in companySalary)
            {
                Console.WriteLine("{0}	 BaseSalary: {1}	Bonus: {2}", salary.Name, salary.BaseSalary, salary.Bonus);
            }
        }
    }
    class Salary : IComparable<Salary>
    {
        public string Name { get; set; }
        public int BaseSalary { get; set; }
        public int Bonus { get; set; }
    
        public int CompareTo(Salary other)
        {
            if (other == null)
            {
                throw new Exception("类型不同,无法比较");
            }
            if (BaseSalary > other.BaseSalary)
            {
                return 1;
            }
            else if (BaseSalary == other.BaseSalary)
            {
                return 0;
            }
            else
            {
                return -1;
            }
            //以上代码可有以下代码代替,使用整型默认比较方法
            //return BaseSalary.CompareTo(other.BaseSalary);
        }
    }
    
    class BonusComparer : IComparer<Salary>
    {
        public int Compare(Salary x, Salary y)
        {
            return x.Bonus.CompareTo(y.Bonus);
        }
    }

     4、Linq实现

      针对前面实现排序方法时,需要实现多个接口,新增了方法使得代码入侵性太高。可扩展性差,对于有新的排序要求,就必须实现新的比较器。使用Linq,可以实现遍历、筛选、投影集合等功能。

    class Program
    {
        public static void Main()
        {
            List<Salary> companySalary = new List<Salary>();
            companySalary.Add(new Salary() { Name = "Mike", BaseSalary = 3000, Bonus = 1000 });
            companySalary.Add(new Salary() { Name = "Rose", BaseSalary = 2000, Bonus = 6000 });
            companySalary.Add(new Salary() { Name = "Tom", BaseSalary = 5000, Bonus = 5000 });
            companySalary.Add(new Salary() { Name = "Jeffry", BaseSalary = 1000, Bonus = 2000 });
            companySalary.Add(new Salary() { Name = "Steve", BaseSalary = 4500, Bonus = 1900 });
            var baseSalarySort = from salary in companySalary orderby salary.BaseSalary select salary;
            foreach (Salary salary in baseSalarySort)
            {
                Console.WriteLine("{0}	 BaseSalary: {1}	Bonus: {2}", salary.Name, salary.BaseSalary, salary.Bonus);
            }
            var bonusSort = from salary in companySalary orderby salary.Bonus select salary;
            foreach (Salary salary in bonusSort)
            {
                Console.WriteLine("{0}	 BaseSalary: {1}	Bonus: {2}", salary.Name, salary.BaseSalary, salary.Bonus);
            }
        }
    }
    class Salary
    {
        public string Name { get; set; }
        public int BaseSalary { get; set; }
        public int Bonus { get; set; }
    }

      Linq可以带来很大的便利性,但需要掌握比较器、迭代器、索引器的原理,以便更好地理解Linq的思想。

    I travel alone,not to be alone.
  • 相关阅读:
    杨辉三角
    数组的两种输出方法
    整数分割各位数
    Fibonacci
    imageview圆角的实现
    listview定位到上次显示的位置
    安卓客户端 扫描二维码登陆
    java,UDP协议简单实现
    java 反射机制的实例
    js中正则表达式 书写方法
  • 原文地址:https://www.cnblogs.com/pilgrim/p/9233486.html
Copyright © 2011-2022 走看看