Sorting in Java & C#
by David Perelman-Hall

Listing One

package dph;

/** Incomplete Employee implementation. Readers can build out this class, and 
possibly add a reference to an instance of type Project to match what 
the Animal class does with type Classification. */

public class Employee
{
     // Member Data
     private String firstname;
     private String lastname;
     private String department;
     private java.util.Date hiredate;
     private Boolean contractorStatus;
     private String manager;
     private Float salary;
     
     // Constructor
     public Employee(String fn, String ln)
     {
          this.firstname = fn;
          this.lastname = ln;
     }
     // Public accessor methods
     public String getFirstName() { return this.firstname; }
     public String getLastName() { return this.lastname; }
     // Public setter methods
     public void setDepartment(String d) { this.department = d; }
     /* Project reference that can be used to test sorting of Employee
     // based on another complex type.  Reader needs to define the
     // Project class so it implements java.lang.Comparable to compare
     // based on some member of the Project type.
     private Project curProject;
     public Project getCurrentProject() { return this.curProject; 
}
     public void setCurrentProject(Project p) { this.curProject = p; }
     */
}


Listing Two 

package dph;
/** Incomplete factory implementation for accessing Comparators
    that know how to compare Employees based on specific properties. */

public class EmployeeComparatorFactory
{
     // Class-level member for determining if types to be compared
     // actually are type Employee.  Used in convertToEmployee method.
     private static Class employeeClass;
     static
     {
          try
          {
               employeeClass = Class.forName("dph.Employee");
          }
          catch(Exception ex)
          {
               ex.printStackTrace();
          }
     }
     // Store the Comparators in this map
     private static java.util.Map<String,java.util.Comparator> map = 
                   new java.util.HashMap<String,java.util.Comparator>();
     // Help ensure singleton pattern--only want one factory to exist.
     private EmployeeComparatorFactory() {}
     // Public class-level interface. Pass all exceptions along for
     // simplicity's sake. Attempt to acquire already-existing Comparator
     // by key from the map, and build one for the map if it doesn't exist.
     // This is the only public interface necessary.
     public static java.util.Comparator 
                   getComparator(String type) throws Exception
     {
          java.util.Comparator comp = map.get(type);
          if(comp == null)
          {
               comp = makeComparator(type);
               map.put(type,comp);
          }
          return comp;
     }
     // Handy for converting Strings to type that can be used in a switch
     enum ComparisonType
     { 
          FIRSTNAME, LASTNAME, DEPARTMENT, HIREDATE, 
          CONTRACTORSTATUS, MANAGER, SALARY
     };
     // The maintenance work goes in here, when need to add new types to
     // be compared on. Convert type to an enum value, switch on enum value
     // and build the appropriate Comparator to be returned from this method.
     // The FactoryComparator class is nested in this class, defined below.
     private static java.util.Comparator 
                          makeComparator(String type) throws Exception
     {
          java.util.Comparator comp = null;
          switch(ComparisonType.valueOf(type.toUpperCase()))
          {
          case FIRSTNAME:
               comp = new FactoryComparator()
               {
                    public int compare(Object obj1, Object obj2)
                    {
                         Employee e1 = convertToEmployee(obj1);
                         Employee e2 = convertToEmployee(obj2);
                         return e1.getFirstName().compareTo(e2.getFirstName());
                    }
               };
               break;
          case LASTNAME:
               //...and so on and so on...
               break;
          }
          return comp;
     }
     // Private helper method to test on type before casting
     private static Employee convertToEmployee(Object obj)
     {
          if(obj.getClass() != EmployeeComparatorFactory.employeeClass)
          {
             throw new RuntimeException(obj + 
                                 " can't be compared as type Employee");
          }
          return (dph.Employee)obj;
     }
     // Private helper abstract implementation of Comparator so don't need
     // to define public boolean equals(Object other) in every case.  This is
     // abstract because it doesn't implement the compareTo method yet.
     private static abstract class 
                       FactoryComparator implements java.util.Comparator
     {
          // Required by java.util.Comparator interface
          public boolean equals(Object other)
          {
               return this.getClass().getName().equals(other.getClass().getName());
          }    
     }
}

Listing Three

using System;
namespace Compare
{
     /// <summary>
     /// Summary description for Animal.
     /// </summary>
     public class Animal
     {
          private string _type;
          private int _age;
          private Classification _class;
          public Animal(string theType, int theAge, Classification theClass)
          {
               this._type = theType;
               this._age = theAge;
               this._class = theClass;
          }
          public override string ToString()
          {
               return this._type + ", " + this._age + " " + this._class;
          }
          // methods
          public string GetAnimalType() { return this._type; }
          public Classification GetClassification() { return this._class; }
          // property
          public int Age 
          { 
               get { return this._age; } 
          }
     }
}


Listing Four

package dph;
/** A (slightly) complex domain-specific type that aggregates the 
    Classification type. */

public class Animal
{
     // Member Data
     private String type;
     private Integer age;
     private Classification _class;
     // Constructor--uses 1.5 autoboxing to convert int to Integer.
     // Requires all three data members to be initialized.
     public Animal(String _type, int age, Classification _class)
     {
          this.type = _type;
          this.age = age;
          this._class = _class;
     }
     // Public accessors for member data
     public Integer getAge() { return this.age; }
     public String getAnimalType() { return this.type; }
     public Classification getClassification() { return this._class; }
     public String toString() { return type + ", " + age + " " + _class; }
}




4


