VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > 编程开发 > Objective-C编程 >
  • 泛型-实现IComparable接口

制作者:剑锋冷月 单位:无忧统计网,www.51stat.net
  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来产生一个0到10之间的随机数:(译者注:参数为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中按两种字段empID或yearsOfSvc来对Employee对象进行排序。
  为了达到这个目的,需要创建IComparer的实现,用于传递给List中Sort()方法的参数。这个IComparer类是EmployeeComparer,它让Employee对象知道如何进行排序。
  EmployeeComparer类有一个WhichComparison属性,它是Employee. EmployeeComparer.ComparisonType类型:
public Employee.EmployeeComparer.ComparisonType WhichComparison
{
  get{return whichComparison;}
  set{whichComparison = value;}
}
  ComparisonType是一个枚举类型,它有两个值:empID或yearsOfSvc(指示您希望按员工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是这个例子的完整代码。为了简化例子,整型数组已经被移除,用于输出的Employee的ToString()方法也增加了代码以让您看得到排序的效果。
  例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接口(这样他们才有可能被排序),这可以通过前面讲述的约束来实现。
  例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" );
   }
  }
}
 


相关教程