zoukankan      html  css  js  c++  java
  • 泛型实现IComparable接口(完)

     

    9.6.1实现IComparable接口

    像所有集合类一样,List实现了Sort()方法,它允许您对所有实现了IComparable接口的对象进行排序。在下一个例子中,您将修改Employee类以实现IComparable

    public class Employee : IComparable<Employee>

    实现IComparable<Employee>接口,Employee对象必须提供CompareTo()方法:

    public int CompareTo(Employee rhs)

    {

       return this.empID.CompareTo(rhs.empID);

    }

    CompareTo()方法把Employee做为参数。我们知道使用Employee是因为这是一个类型安全的集合。当前Employee对象必须把它自己跟做为参数传递进来的Employee进行对比,如果返回-1,表示它小于参数,如果大于参数则返回1,如果两者相等则返回0。这意味着决定大于、小于、等于的是Employee。在本例中,您委托成员empId进行比较。empId成员是一个int类型,并使用了整数类型默认的CompareTo()方法,以对比两个值之间的大小。

    System.Int32类实现了Icomparable<Int32>接口,所以您可以把比较的职责委托给整数类型。

    您现在准备对员工数组列表(empList)进行排序,为了查看排序是否正常工作,您需要随机地添加整数和Employee实例到它们各自的数组中。创建随机数,需要实例化Random类;调用Random对象的Next()方法产生随机数。Next()方法是一个重载方法;一种版本允许您传递一个整数值,表示您想要的最大随机数。在本例中,您将传递10来产生一个010之间的随机数:(译者注:参数为10,最大的随机数只能为9

    Random r = new Random();

    r.Next(10);

    9-14创建了一个整型数组和一个Employee数组,并给两者填充随机数,并打印它们的值。随后排序数组并打印新值。

    9-14 排序整数和employee数组


    using System;
    using System.Collections.Generic;
    using System.Text;

    namespace IComparable
    {
       
    // 一个简单的用于存储在数组中的类
       public class Employee : IComparable<Employee>
       {
          
    private int empID;
          
    public Employee( int empID )
          {
             
    this.empID = empID;
          }
          
    public override string ToString( )
          {
             
    return empID.ToString( );
          }
          
    public bool Equals( Employee other )
          {
             
    if ( this.empID == other.empID )
             {
                
    return true;
             }
             
    else
             {
                
    return false;
             }
          }
          
    // Employee使用整数默认的CompareTo方法
          public int CompareTo( Employee rhs )
          {
             
    return this.empID.CompareTo( rhs.empID );
          }
       }
       
    public class Tester
       {
          
    static void Main( )
          {
             List
    <Employee> empArray = new List<Employee>( );
             List
    <Int32> intArray = new List<Int32>( );
             
    // 产生整数和employee的ID的随机数
             Random r = new Random( );
             
    // 填充数组
             for ( int i = 0; i < 5; i++ )
             {
                
    // 添加随机的employee的id
                empArray.Add( new Employee( r.Next( 10 ) + 100 ) );
                
    // 添加随机的整数
                intArray.Add( r.Next( 10 ) );
             }
             
    // 显示整型数组中的所有内容
             for ( int i = 0; i < intArray.Count; i++ )
             {
                Console.Write( 
    "{0} ", intArray[i].ToString( ) );
             }
             Console.WriteLine( 
    "\n" );
             
    // 显示Employee数组中的所有内容
             for ( int i = 0; i < empArray.Count; i++ )
             {
                Console.Write( 
    "{0} ", empArray[i].ToString( ) );
             }
             Console.WriteLine( 
    "\n" );
             
    // 整型数组排序
             intArray.Sort( );
             
    for ( int i = 0; i < intArray.Count; i++ )
             {
                Console.Write( 
    "{0} ", intArray[i].ToString( ) );
             }
             Console.WriteLine( 
    "\n" );
             
    // employee数组排序并显示
             
    //原文的下面这两句应该注释掉,现在还没用到
             
    //Employee.EmployeeComparer c = Employee.GetComparer( );
             
    //empArray.Sort(c);
             empArray.Sort( );
             
    // 显示Employee数组中的所有内容
             for ( int i = 0; i < empArray.Count; i++ )
             {
                Console.Write( 
    "{0} ", empArray[i].ToString( ) );
             }
             Console.WriteLine( 
    "\n" );
          }
       }
    }

     

    输出结果:

    4 5 6 5 7

    108 100 101 103 103

    4 5 5 6 7

    100 101 103 103 108

    输出显示整型数组和Employee数组产生的是随机数。排序后,显示的是已经进行排序后的值。

    9.6.2 实现IComparer接口

    当您在List中调用Sort(),默认的IComparer译者注:这里可能是错误,应该为IComparable)实现被调用,它调用IComparable所实现的CompareTo()方法对List内的每个元素进行快速排序。

    当您想控制排列方式时,可以自由地创建自己的IComparer实现。在下一个例子中,将在Employee中添加第二个字段:yearsOfSvc。您希望在List中按两种字段empIDyearsOfSvc来对Employee对象进行排序。

    为了达到这个目的,需要创建IComparer的实现,用于传递给ListSort()方法的参数。这个IComparer类是EmployeeComparer,它让Employee对象知道如何进行排序。

    EmployeeComparer类有一个WhichComparison属性,它是Employee. EmployeeComparer.ComparisonType类型:

    public Employee.EmployeeComparer.ComparisonType WhichComparison

    {

       get{return whichComparison;}

       set{whichComparison = value;}

    }

    ComparisonType是一个枚举类型,它有两个值:empIDyearsOfSvc(指示您希望按员工ID还是工龄进行排序):

    public enum ComparisonType

    {

       EmpID,

       YearsOfService

    };

    在调用Sort()方法之前,创建EmployeeComparer的实例并设置它的ComparisonType属性:

    Employee.EmployeeComparer c = Employee.GetComparer();

    c.WhichComparison=Employee.EmployeeComparer.ComparisonType.EmpID;

    empArray.Sort(c);

    调用Sort()方法之时,List会调用EmployeeComparer中的Compare方法,并把当前要对比的字段通过WhickComparison属性传递给Employee.CompareTo()方法:

    public int Compare( Employee lhs, Employee rhs )

    {

        return lhs.CompareTo( rhs, WhichComparison );

    }

    Employee对象必须实现一个自定义的CompareTo()方法,用于获得比较方式并按照要求进行对比:

    public int CompareTo(Employee rhs,

        Employee.EmployeeComparer.ComparisonType which)

    {

       switch (which)

       {

          case Employee.EmployeeComparer.ComparisonType.EmpID:

             return this.empID.CompareTo(rhs.empID);

          case Employee.EmployeeComparer.ComparisonType.Yrs:

             return this.yearsOfSvc.CompareTo(rhs.yearsOfSvc);

       }

       return 0;

    }

    9-15是这个例子的完整代码。为了简化例子,整型数组已经被移除,用于输出的EmployeeToString()方法也增加了代码以让您看得到排序的效果。

    9-15 按员工的ID和工龄进行排序

    using System;
    using System.Collections.Generic;
    using System.Text;

    namespace IComparer
    {
        
    public class Employee : IComparable<Employee>
        {
            
    private int empID;
            
    private int yearsOfSvc = 1;
            
    public Employee(int empID)
            {
                
    this.empID = empID;
            }
            
    public Employee(int empID, int yearsOfSvc)
            {
                
    this.empID = empID;
                
    this.yearsOfSvc = yearsOfSvc;
            }
            
    public override string ToString()
            {
                
    return "ID:" + empID.ToString() +
                    
    ". Years of Svc:" + yearsOfSvc.ToString();
            }
            
    public bool Equals(Employee other)
            {
                
    if (this.empID == other.empID)
                {
                    
    return true;
                }
                
    else
                {
                    
    return false;
                }
            }
            
    //静态方法,用于获取一个Comparer对象
            public static EmployeeComparer GetComparer()
            {
                
    return new Employee.EmployeeComparer();
            }
            
    public int CompareTo(Employee rhs)
            {
                
    return this.empID.CompareTo(rhs.empID);
            }
            
    //通过自定义comparer来调用指定的实现
            public int CompareTo(Employee rhs,
                Employee.EmployeeComparer.ComparisonType which)
            {
                
    switch (which)
                {
                    
    case Employee.EmployeeComparer.ComparisonType.EmpID:
                        
    return this.empID.CompareTo(rhs.empID);
                    
    case Employee.EmployeeComparer.ComparisonType.Yrs:
                        
    return this.yearsOfSvc.CompareTo(rhs.yearsOfSvc);
                }
                
    return 0;
            }
            
    //实现IComparer接口的嵌套类
            public class EmployeeComparer : IComparer<Employee>
            {
                
    private Employee.EmployeeComparer.ComparisonType
                    whichComparison;
                
    //比较方式枚举
                public enum ComparisonType
                {
                    EmpID,
                    Yrs
                };
                
    public bool Equals(Employee lhs, Employee rhs)
                {
                    
    return this.Compare(lhs, rhs) == 0;
                }
                
    public int GetHashCode(Employee e)
                {
                    
    return e.GetHashCode();
                }
                
    public int Compare(Employee lhs, Employee rhs)
                {
                    
    return lhs.CompareTo(rhs, WhichComparison);
                }
                
    public Employee.EmployeeComparer.ComparisonType
                    WhichComparison
                {
                    
    get { return whichComparison; }
                    
    set { whichComparison = value; }
                }
            }
        }
        
    public class Tester
        {
            
    static void Main()
            {
                List
    <Employee> empArray = new List<Employee>();
                Random r 
    = new Random();
                
    for (int i = 0; i < 5; i++)
                {
                    
    //添加一个随机的员工ID
                    empArray.Add(new Employee(
                        r.Next(
    10+ 100, r.Next(20)));
                }
                
    //显示Employee数组的所有内容
                for (int i = 0; i < empArray.Count; i++)
                {
                    Console.Write(
    "\n{0} ", empArray[i].ToString());
                }
                Console.WriteLine(
    "\n");
                
    //排序并显示Employee数组
                Employee.EmployeeComparer c = Employee.GetComparer();
                c.WhichComparison 
    =
                    Employee.EmployeeComparer.ComparisonType.EmpID;
                empArray.Sort(c);
                
    //显示Employee数组的所有内容
                for (int i = 0; i < empArray.Count; i++)
                {
                    Console.Write(
    "\n{0} ", empArray[i].ToString());
                }
                Console.WriteLine(
    "\n");

                c.WhichComparison 
    = Employee.EmployeeComparer.ComparisonType.Yrs;
                empArray.Sort(c);
                
    for (int i = 0; i < empArray.Count; i++)
                {
                    Console.Write(
    "\n{0} ", empArray[i].ToString());
                }
                Console.WriteLine(
    "\n");
            }
        }
    }

     

    输出结果:

    ID: 103. Years of Svc: 11

    ID: 108. Years of Svc: 15

    ID: 107. Years of Svc: 14

    ID: 108. Years of Svc: 5

    ID: 102. Years of Svc: 0

     

    ID: 102. Years of Svc: 0

    ID: 103. Years of Svc: 11

    ID: 107. Years of Svc: 14

    ID: 108. Years of Svc: 15

    ID: 108. Years of Svc: 5

     

    ID: 102. Years of Svc: 0

    ID: 108. Years of Svc: 5

    ID: 103. Years of Svc: 11

    ID: 107. Years of Svc: 14

    ID: 108. Years of Svc: 15

    第一块输出显示的是Employee对象被加进List时的情形。员工ID值和工龄是随机顺序的。第二块显示的是按员工ID排序后的结果,第三块显示的是按工龄排序后的结果。

    如果您如例9-11那样创建自己的集合,并希望实现IComparer,可能需要确保所有放在列表中的类型都实现了IComparer接口(这样他们才有可能被排序),这可以通过前面讲述的约束来实现。

     

  • 相关阅读:
    微信小程序右上角胶囊的位置
    NLP复习大纲
    网站收藏
    css中如何调整插入背景图片的大小
    禁止Power Apps Canvas用户通过SharePoint Online UI界面访问站点list
    c++ vector基本知识
    c++ map基本知识
    c++ string操作
    python学习笔记30:操作excel
    c++, 如何run一个c++程序
  • 原文地址:https://www.cnblogs.com/abatei/p/1066837.html
Copyright © 2011-2022 走看看