Again, the topic on Collection usage seems overlooked by most Java developers. Sorting is something that's very common in any programming world, therefore we shouldn't bother to reinvent the wheel for such purpose. As common as it is, yet not many of us know how to do it correctly and efficiently.
In the real business world, there are many cases where we're required to perform sorting on a Collection of some user-defined objects. If the element of the Collection is a String type, or any other class which implements Comparable, then the sorting can be performed in the natural order. But sometimes, we want to perform a different criteria for sorting, or probably we want to sort a user-defined type.
Here's where Comparator comes into play. Clean and extensible.
Here's an example of a simplified user-defined type:
public class Customer {
private String firstName;
private String middleName;
private String lastName;
// setter & getter methods..
}
In the above class, the most commonly found as natural ordering would be order by lastName. This can easily be implemented using the Comparable interface, i.e.
public class Customer implements Comparable {
// as shown previously..
public int compareTo (Object o) {
if (o == null || !(o instanceof Customer)) {
throw new IllegalArgumentException ("...");
}
Customer c = (Customer) o;
String cLastName = c.getLastName();
if (lastName == null && cLastName == null) return 0;
// assuming you want null values shown last
if (lastName != null && cLastName == null) return -1;
if (lastName == null && cLastName != null) return 1;
return lastName.compareTo (cLastName);
}
}
Sorting a List of Customer objects would be as simple as:
Collections.sort (customerList);
But, if we want to use a different ordering, e.g. order by the first name, then we cannot use the natural ordering as defined within the Customer class. Instead, we have to define an alternative ordering, in the form of a Comparator class.
public class CustomerFirstNameComparator
implements Comparator {
// use singleton whenever possible..
public int compare (Object o1, Object o2) {
if (o1 == null && o2 == null) return 0;
// assuming you want null values shown last
if (o1 != null && o2 == null) return -1;
if (o1 == null && o2 != null) return 1;
if (!(o1 instanceof Customer) ||
!(o2 instanceof Customer)) {
throw new IllegalArgumentException ("...");
}
Customer c1 = (Customer) o1;
Customer c2 = (Customer) o2;
String firstName1 = c1.getFirstName();
String firstName2 = c2.getFirstName();
if (firstName1 == null && firstName2 == null) return 0;
// assuming you want null values shown last
if (firstName1 != null && firstName2 == null) return -1;
if (firstName1 == null && firstName2 != null) return 1;
return firstName1.compareTo (firstName2);
}
}
Sorting a List of Customer objects by their first name, would be:
// assuming you implement singleton..
Comparator comparator =
CustomerFirstNameComparator.getInstance();
Collections.sort (customerList, comparator);
Simple, clean & extensible. You can start defining more and more Comparator classes to suit your needs. As it is a Java class, you can also perform complex comparison on the objects.