Friday, September 14, 2007

Composite Comparator - Fun with generics and varargs

A couple of new features in Java 5 are the additions of generics and varargs. We use generics a lot when returning a list from our DAOs but I've never had to implement a method that accepted varargs until I implemented this parent reviews page.

This is a typical page where a user may sort by date or by rating. Another feature is that a principal's review for a school always comes first. So the sorting is like so:

  1. By Principal, then date descending
  2. By Principal, then date ascending
  3. By Principal, then rating, then descending

First thing I needed to do was create a couple of comparators. I used the static final comparator approach that that Josh Block talks about in Effective Java. I'll demonstrate with a baseball class. The nice thing about the composite comparator is that now I can create a comparator based on hr,rbi, and anything else I wanted to add later like sb, runs, etc.

Example:
public class BaseBallPlayer {

   private int _rbi;

   private int _hr;



   public BaseBallPlayer(int rbi, int hr) {

       _rbi = rbi;

       _hr = hr;

   }



   public static final Comparator HR_COMPARATOR = new Comparator<BaseBallPlayer>() {

       public int compare(BaseBallPlayer o1, BaseBallPlayer o2) {

           return o1.getRbi() - o2.getRbi();

       }

   };



   public static final Comparator RBI_COMPARATOR = new Comparator<BaseBallPlayer>() {

       public int compare(BaseBallPlayer o1, BaseBallPlayer o2) {

           return o1.getHr() - o2.getHr();

       }

   };



   public int getHr() {

       return _hr;

   }



   public int getRbi() {

       return _rbi;

   }

}

public class GenericComparator {

   public static <T>Comparator<T> createComparator(final Comparator<T>... c) {

       return new Comparator<T>() {

           public int compare(T r1, T r2) {

               int result = 0;

               for (Comparator<T> comp : c) {

                   result = comp.compare(r1, r2);

                   if (result != 0) {

                       break;

                   }

               }

               return result;

           }

       };

   }

}

   Comparator<BaseBallPlayer> HR_RBI_COMPARATOR = GenericComparator.<BaseBallPlayer>createComparator(

                   BaseBallPlayer.HR_COMPARATOR, BaseBallPlayer.RBI_COMPARATOR);

2 comments:

knguyenit said...

Nice article. Thank you!

Karthika Shree said...

Finding the time and actual effort to create a superb article like this is great thing. I’ll learn many new stuff right here! Good luck for the next post buddy..
Java Training in Chennai