Tuesday, August 13, 2013

How To Sort Java Objects Using Comparable And Comparator ?

Sort an Object with Comparable
How about a Java Object? Let create a City class:
public class City {

       private String cityName;
       private int cityPopulation;
       private int pinCode;

       public City(String cityName, int cityPopulation, int pinCode) {
              super();
              this.cityName = cityName;
              this.cityPopulation = cityPopulation;
              this.pinCode = pinCode;
       }

       public String getCityName() {
              return cityName;
       }

       public void setCityName(String cityName) {
              this.cityName = cityName;
       }

       public int getCityPopulation() {
              return cityPopulation;
       }

       public void setCityPopulation(int cityPopulation) {
              this.cityPopulation = cityPopulation;
       }

       public int getPinCode() {
              return pinCode;
       }

       public void setPinCode(int pinCode) {
              this.pinCode = pinCode;
       }
}

To sort it, you may think of Arrays.sort() again, see below example :


import java.util.Arrays;

public class SortObjest {

       /**
        * @param args
        */
       public static void main(String args[]) {

              City[] cities = new City[4];

              City hyd = new City("Hyderabad", 1111111, 500081);
              City cn = new City("Chennai", 2222222, 600020);
              City vz = new City("Vizag", 3333333, 530012);
              City tpt = new City("Tirupati",4444444, 517501);

              cities[0] = hyd;
              cities[1] = cn;
              cities[2] = vz;
              cities[3] = tpt;

              Arrays.sort(cities);

              int i = 0;
              for (City temp : cities) {
                     System.out.println("city " + ++i + " : " + temp.getCityName()
                                  + ", PinCode : " + temp.getPinCode());
              }

       }

}


Nice try, but, what you expect the Arrays.sort() will do? You didn’t even mention what to sort in the City class. So, it will hits the following error :

Exception in thread "main" java.lang.ClassCastException: new1.City cannot be cast to java.lang.Comparable
       at java.util.Arrays.mergeSort(Arrays.java:1144)
       at java.util.Arrays.sort(Arrays.java:1079)
       at new1.SortObjest.main(SortObjest.java:24)

To sort an Object by its property, you have to make the Object implement the Comparable interface and override thecompareTo() method. Lets see the new City class again.
public class City implements Comparable<City> {

       private String cityName;
       private int cityPopulation;
       private int pinCode;

       public City(String cityName,int  cityPopulation, int pinCode) {
              super();
              this.cityName = cityName;
              this.cityPopulation = cityPopulation;
              this.pinCode = pinCode;
       }

       public String getCityName() {
              return cityName;
       }

       public void setCityName(String cityName) {
              this.cityName = cityName;
       }

       public int getCityPopulation() {
              return cityPopulation;
       }

       public void setCityPopulation(int cityPopulation) {
              this.cityPopulation = cityPopulation;
       }

       public int getPinCode() {
              return pinCode;
       }

       public void setPinCode(int pinCode) {
              this.pinCode = pinCode;
       }

       public int compareTo(City compareCity) {

              int comparePinCode = ((City) compareCity).getPinCode();

              // ascending order
              return this.pinCode - comparePinCode;

              // descending order
              // return comparePinCode - this.pinCode;

       }
}

 The new City class implemented the Comparable interface, and overrided the compareTo() method to compare its pinCode property in ascending order.
The compareTo() method is hard to explain, in integer sorting, just remember
1.    this.pinCode – comparePinCode is ascending order.
2.    comparePinCode – this.pinCode is descending order.
To understand more about compareTo() method, read this Comparable documentation.
Run it again, now the Cities array is sort by its pinCode in ascending order.
OUTPUT:
city 1 : Hyderabad, PinCode : 500081
city 2 : Tirupati, PinCode : 517501
city 3 : Vizag, PinCode : 530012
city 4 : Chennai, PinCode : 600020

Sort an Object with Comparator
How about sorting with City’s “cityName” or “PinCode”? The Comparable interface is only allow to sort a single property. To sort with multiple properties, you need Comparator. See the new updated City class again :
import java.util.Comparator;

public class City implements Comparable<City> {

       private String cityName;
       private int cityPopulation;
       private int pinCode;

       public City(String cityName, int cityPopulation, int pinCode) {
              super();
              this.cityName = cityName;
              this.cityPopulation = cityPopulation;
              this.pinCode = pinCode;
       }

       public String getCityName() {
              return cityName;
       }

       public void setCityName(String cityName) {
              this.cityName = cityName;
       }

       public int getCityPopulation() {
              return cityPopulation;
       }

       public void setCityPopulation(int cityPopulation) {
              this.cityPopulation = cityPopulation;
       }

       public int getPinCode() {
              return pinCode;
       }

       public void setPinCode(int pinCode) {
              this.pinCode = pinCode;
       }

       public int compareTo(City compareCity) {

              int comparePinCode = ((City) compareCity).getPinCode();

              // ascending order
              return this.pinCode - comparePinCode;

              // descending order
              // return comparePinCode - this.pinCode;

       }

       public static Comparator<City> CityNameComparator = new Comparator<City>() {

              public int compare(City city1, City city2) {

                     String cityName1 = city1.getCityName().toUpperCase();
                     String cityName2 = city2.getCityName().toUpperCase();

                     // ascending order
                     return cityName1.compareTo(cityName2);

                     // descending order
                     // return cityName2.compareTo(cityName1);
              }

       };
}

The City class contains a static CityNameComparator method to compare the “cityName”. Now the City object is able to sort with either “pinCode” or “cityName” property. Run it again.
1. Sort City array based on its “cityName” property in ascending order.
Arrays.sort(cities, City.CityNameComparator);

Output
city 1 : Chennai, PinCode : 600020
city 2 : Hyderabad, PinCode : 500081
city 3 : Tirupati, PinCode : 517501
city 4 : Vizag, PinCode : 530012

2. Sort City array based on its “pinCode” property in ascending order.
Arrays.sort(cities)
Output
city 1 : Hyderabad, PinCode : 500081
city 2 : Tirupati, PinCode : 517501
city 3 : Vizag, PinCode : 530012
city 4 : Chennai, PinCode : 600020


The java.lang.Comparable and java.util.Comparator are powerful but take time to understand and make use of it, may be it’s due to the lacking of detail example.


No comments:

Post a Comment