CompareTo Overide Sort

2019-08-17 18:16发布

问题:

I am having an issue overiding a compareTo methods. The program simulates different employee types, and I have it sorting by employee type perfectly, but can not get it to do a secondary sort by gross pay. Once it sorts by class name/employee type, it then needs to sort by grossPay, which I can obtain by a helper method. Below is the code:

  public int compareTo(Object o) {

    Employee other = (Employee) o;

    if(other instanceof Salaried)
        return -1;

    else if(other instanceof Daily)
         return 1; 

    else
        return 0;
}

I am using Collection.sort() with an arraylist of employess. When I print out I get a great sorted list by employee type, but it should then sort by grossPay.

回答1:

The compareTo must return results consistent with a total order. Otherwise the sort results are not guaranteed in any way. A total order means that if A<B, then B>A and if A==B, then B==A. In other words, you can switch this and other and the results are consistent. The code you present does not do this even for employee type.

If compareTo isn't consistent with at total order, sort can produce the wrong answer or never terminate.

It's not clear if your system has 3 types of employees or 2. Let's assume it's 2: salaried and daily. Then we need to work through the possiblities:

this     other    result
------------------------
salaried salaried equal
daily    salaried <
salaried daily    >
daily    daily    equal

Only after we've established that this and other are equal in employee type do we take the secondary sort key, which is gross pay.

So one way to code this is:

// Assume this and o have type Daily or Salaried.
public int compareTo(Object o) {
  if (this instanceof Daily && o instanceof Salaried) return -1;
  if (this instanceof Salaried && o instanceof Daily) return +1;
  // The employee types must be equal, so make decision on pay.
  Employee e = (Employee)o;
  return grossPay() < e.grossPay() ? -1 :
         grossPay() > e.grossPay() ? +1 : 0;
}

I'm assuming this is implemented in Employee.

Finally, it would probably be better to implement this sort with a Comparator. The compareTo method should be reserved for the "natural" sort order such as the numerical order of a unique id number that serves as a primary key. This sort criterion doesn't seem to be "natural".



回答2:

You can compare grossPay after the comparing of type.Assuming grossPay is a number.

public int compareTo(Object o) {

    Employee other = (Employee) o;
    if(this instanceof Daily && other instanceof Salaried)
        return -1;

    else if(this instanceof Salaried && other instanceof Daily)
        return 1; 

    else
        return this.getGrossPay() - other.getGrossPay();
}