IComparable

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了IComparable相关的知识,希望对你有一定的参考价值。

有对象的地方就会存在比较,就像小时候每次拿着考卷回家,妈妈都会问你隔壁的那谁谁谁考了多少分呀。下面我们也来举个简单的例子,就是有几个人的Salary列表。我们根据基本工资来进行罗列:

技术分享
    class Program
    {
        static void Main(string[] args)
        {
            ArrayList array = new ArrayList();
            array.Add(1100);
            array.Add(1200);
            array.Add(1160);
            array.Sort();
            foreach (var obj in array)
            {
                Console.WriteLine(obj.ToString());
            }
            Console.ReadLine();
        }
    }
技术分享

技术分享 可以发现通过ArrayList.Sort()方法即可完成排序的任务。不过ArrayList这里只能是一个字段的。假如有姓名、工资两个字段,然后根据工资进行排序那么按照现在的情况来看,ArrayList是无法实现的。所以接口IComparable现在可以派上用场了。现在先定义一个实体,并且实现接口IComparable。

技术分享
public class Salary:IComparable
    {
        /// <summary>
      /// 姓名
        /// </summary>
      public string Name { get; set; }

        /// <summary>
      /// 基本工资
        /// </summary>
      public int BaseSalary { get; set; }

        /// <summary>
      /// 实现IComparable接口
        /// </summary>
      /// <param name="obj"></param>
        /// <returns></returns>
      public int CompareTo(object obj)
        {
            Salary staff = obj as Salary;
            if (BaseSalary > staff.BaseSalary)
            {
                return 1;
            }
            else if (BaseSalary == staff.BaseSalary)
            {
                return 0;
            }
            else
            {
                return -1;
            }
        }
    }
技术分享

进行排序

技术分享
                ArrayList array = new ArrayList();
                array.Add(new Salary() { Name = "aehyok", BaseSalary = 12000 });
                array.Add(new Salary() { Name = "Kris", BaseSalary = 11200 });
                array.Add(new Salary() { Name = "Leo", BaseSalary = 18000 });
                array.Add(new Salary() { Name = "Niki", BaseSalary = 20000 });
                array.Sort();
                foreach (Salary obj in array)
                {
                    Console.WriteLine(string.Format("{0} BaseSalary:{1}", obj.Name, obj.BaseSalary));
                }
                Console.ReadLine();
技术分享

如果未继承Icomparable接口。那么会出现如下错误。

技术分享

正确的进行排序,结果如下所示

技术分享

假如现在在Salary类中添加了一个奖金的字段如下

技术分享
public class Salary:IComparable
    {
        /// <summary>
      /// 姓名
        /// </summary>
      public string Name { get; set; }

        /// <summary>
      /// 基本工资
        /// </summary>
      public int BaseSalary { get; set; }

        /// <summary>
      /// 奖金
        /// </summary>
      public int Bouns { get; set; }

        /// <summary>
        /// 实现IComparable接口
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
      public int CompareTo(object obj)
        {
            Salary staff = obj as Salary;
            if (BaseSalary > staff.BaseSalary)
            {
                return 1;
            }
            else if (BaseSalary == staff.BaseSalary)
            {
                return 0;
            }
            else
            {
                return -1;
            }
        }
    }
技术分享

再继续假如,现在又要以Bouns奖金字段进行排序,那应该怎么处理呢?当然修改Salary实体类中继承的接口方法进行处理肯定是没问题了,但是比较麻烦。我们可以采用自定义比较接口IComparer来实现。


    public class BounsComparer:IComparer
    {
        public int Compare(object x, object y)
        {
            Salary s1 = x as Salary;
            Salary s2 = y as Salary;
            return s1.Bouns.CompareTo(s2.Bouns);
        }
    }

然后重新进行排序


                ArrayList array = new ArrayList();
                array.Add(new Salary() { Name = "aehyok", BaseSalary = 12000,Bouns=500 });
                array.Add(new Salary() { Name = "Kris", BaseSalary = 11200,Bouns=400 });
                array.Add(new Salary() { Name = "Leo", BaseSalary = 18000,Bouns=300 });
                array.Add(new Salary() { Name = "Niki", BaseSalary = 20000,Bouns=700 });
                array.Sort(new BounsComparer());
                foreach (Salary obj in array)
                {
                    Console.WriteLine(string.Format("{0} \\tBaseSalary:{1}\\tBouns{2}", obj.Name, obj.BaseSalary,obj.Bouns));
                }
                Console.ReadLine();
技术分享

结果如下所示

技术分享

注意,刚才实现接口名字叫IComparable,而自定义的比较器接口是IComparer

如果我们稍有经验,会发现如下函数中的问题

        public int Compare(object x, object y)
        {
            Salary s1 = x as Salary;
            Salary s2 = y as Salary;
            return s1.Bouns.CompareTo(s2.Bouns);
        }

这个函数中进行了转型处理,这是会影响性能的。如果集合中有成千上万个复杂的实体对象,那么进行排序时耗费的时间是巨大的。所以泛型登场,很好的解决了这个问题。

因此以上代码中的ArrayList,可以替换为List<T>,对应的我们就应该实现IComparable<T>和IComparer<T>。

实现的代码如下:  

1、实体类实现接口IComparable<T>  2、自定义比较器实现接口IComparer<T> 3、进行排序的调用

public class Salary:IComparable<Salary>
    {
        /// <summary>
      /// 姓名
        /// </summary>
      public string Name { get; set; }
      /// <summary>
      /// 基本工资
        /// </summary>
      public int BaseSalary { get; set; }

        /// <summary>
      /// 奖金
        /// </summary>
      public int Bouns { get; set; }

        /// <summary>
      /// 实现IComparable接口
        /// </summary>
      /// <param name="obj"></param>
      /// <returns></returns>
      public int CompareTo(Salary other)
        {
            return BaseSalary.CompareTo(other.BaseSalary);
        }
    }


    public class BounsComparer : IComparer<Salary>
    {
        public int Compare(Salary x, Salary y)
        {
            return x.Bouns.CompareTo(y.Bouns);
        }
    }


                List<Salary> array =new List<Salary>();
                array.Add(new Salary() { Name = "aehyok", BaseSalary = 12000,Bouns=500 });
                array.Add(new Salary() { Name = "Kris", BaseSalary = 11200,Bouns=400 });
                array.Add(new Salary() { Name = "Leo", BaseSalary = 18000,Bouns=300 });
                array.Add(new Salary() { Name = "Niki", BaseSalary = 20000,Bouns=700 });
                array.Sort(new BounsComparer());
                foreach (Salary obj in array)
                {
                    Console.WriteLine(string.Format("{0} \\tBaseSalary:{1}\\tBouns{2}", obj.Name, obj.BaseSalary,obj.Bouns));
                }
                Console.ReadLine();

最终结果

技术分享









以上是关于IComparable的主要内容,如果未能解决你的问题,请参考以下文章