java.util.Comparator is used to define a special sort order for a class.
- Use the ComparatorCutter to mindlessly crank out complete code for Comparables and Comparators.
The code will help teach you the structure so that you can write them without such training wheels.
- How do you remember that java.util. Comparable. compareTo
defines a natural order where java.util. Comparator. compare defines an auxiliary order?
I think about it this way:
“Does it makes sense to compare two Oranges? If so they are Comparable.
I will need a method that compares this Orange Object to (compareTo)
another. If I want do define an alternate order, I need to invent some sort of independent machine, a Comparator to do it.
The comparison is not inherent to Oranges, so there is no this. Instead, I compare two Orange
Objects.”
To implement java.util.Comparator you must write two methods. It typically describes a small delegate object passed to a sort to describe some
special sort order. The compare method compares two objects of the class you want to sort. The equals method compares
this java.util.Comparator to another to see if they represent the same order. It does not compare two objects of the class you want to
sort. Normally you also redefine equals when you implement Comparator even though it is not part of the Comparator
interface. There are no generics involved in overriding equals.
public final int compare( Object o1, Object o2 );
public boolean equals( Object obj );
Here is a typical java.util.Comparator.compare routine:
If you are using a java.util.Comparator only once, you might implement it as an anonymous inner class like this:
Collections.sort( myArrayList, new Comparator()
{
public int compare( Object a, Object b )
{
return( (String)a ).compareToIgnoreCase( (String) b );
}
} );
Here is a very general purpose Comparator for sorting rows of a Table (array of arrays or Vector of arrays) where each element is some sort of
Object that implements Comparable.
Tips
- If you make your Comparators nested static classes of the class they sort, they will be easy to find and easy to
associate with the correct class.
- String.CASE_INSENSITIVE_ORDER is a Comparator you can use without writing any code. Unfortunately there is no String.CASE_SENSITIVE_ORDER.
The reason is String’s Comparable implementation provides it naturally without a Comparator. You can use
the following code to sort by natural Comparable order when a Comparator is required.
- Beware of using subtraction in writing Comparators rather than < > and Double. compareTo
if there is any possibility you will be using numbers large enough to overflow and give the wrong sign comparing them with subtraction. The other problem with subtraction is
it might give a long or double result which is not an integer value suitable for return.
Descending/Inverse/Reverse Order with reverseOrder
Sorting ascending order means sorting with the small elements first then the big. This is
usual ordering. Descending order means sorting with the big elements first then the small.
If you have a Comparator or Comparable
of some kind, you can convert it into one that sorts into the reverse of the usual order. E.g. if the original sorts
alphabetically, the new one will sort in reverse alphabetical order. Here is how you use it:
If you don’t have a suitable base Comparator,
just write an ordinary Comparator from scratch and reverse the operands to each compare
inside it, or return - result instead of result.
Comparator Using Generics
You don’t need any casts since the compiler checks that no non-Pair classes ever get inside the ArrayList<Pair>.
Learning More
Sun’s Javadoc on the
Comparable class : available:
Note java.lang.Comparable but java. util.Comparator.
Sun’s Javadoc on the
Comparator class : available:
Sun’s Javadoc on
Collections.
reverseOrder() : available:
Sun’s Javadoc on
Collections.
reverseOrder(Comparator) : available: