July 03, 2014

Comparable & Comparator API

Total order
A total order is a binary relation ≤ that satisfies:
・Antisymmetry: if v ≤ w and w ≤ v, then v = w.
・Transitivity: if v ≤ w and w ≤ x, then v ≤ x.
・Totality: either v ≤ w or w ≤ v or both.
Ex.
・Standard order for natural and real numbers.
・Chronological order for dates or times.
・Alphabetical order for strings.

 Note that the <= operator for double is not a total order. Double.NaN <= Double.NaN is false.

Comparable API
Implement compareTo() so that v.compareTo(w)
・Is a total order.
・Returns a negative integer, zero, or positive integer
if v is less than, equal to, or greater than w, respectively.
・Throws an exception if incompatible types (or either is null).

Tips:
To sort an Array, use the Arrays.sort().
To sort an ArrayList, use the Collections.sort().

Natural Sorting of numbers:

Output: 1,2,3,5,7,10,16,23,46

Incorrect sorting of cars:
Let us consider taking a car class with the data members as shown below.


Here the client tries to sort an array consisting of three cars. But do you see the problem?

Yes. This cannot be sorted by Java because we haven't told it what is the order to be followed and which data member should be considered to be sorted. This is why we implement the comparable interface. The output of above as expected would be.

Correct Sorting of Cars:
Shown below is the class diagram:

Here the Car class now implements the comparable Interface and defines the total order in compareTo() method.
Output: Mazda,Honda,Toyota

Correct Sorting of Cars with different properties:
You do not have to implement Comparable but you have to create static members of type Comparator which overrides the method compare(). Below is shown the class diagram.
Code:
package george.comparablesWithComparator;

import java.util.Comparator;

public class Car{

private String make;
private String model;
private int cost;
public String getMake() {
return make;
}
public void setMake(String make) {
this.make = make;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public int getCost() {
return cost;
}
public void setCost(int cost) {
this.cost = cost;
}
public static Comparator carCostComparator = new Comparator() {

@Override
public int compare(Car c1, Car c2) {
if(c1.cost < c2.cost)
return -1;
else if(c1.cost > c2.cost)
return 1;
else
return 0;
}
};
public static Comparator carModelComparator = new Comparator() {

@Override
public int compare(Car c1, Car c2) {
if(c1.model.compareTo(c2.model) < 0)
return -1;
else if(c1.model.compareTo(c2.model) > 0)
return 1;
else
return 0;
}
};
public static Comparator carMakeComparator = new Comparator() {

@Override
public int compare(Car c1, Car c2) {
if(c1.make.compareTo(c2.make) < 0)
return -1;
else if(c1.make.compareTo(c2.make) > 0)
return 1;
else
return 0;
}
};
}


package george.comparablesWithComparator;

import java.util.Arrays;

public class ClassClient {

/**
* @param args
*/
public static void main(String[] args) {
Car car1 = new Car();
Car car2 = new Car();
Car car3 = new Car();
car1.setCost(1000);
car1.setMake("Honda");
car1.setModel("City");
car2.setCost(120);
car2.setMake("Mazda");
car2.setModel("ZX-1");
car3.setCost(90888);
car3.setMake("Toyota");
car3.setModel("Qualis");
Car[] carArray = {car1, car2, car3};
System.out.print("Sorting by Make: ");
Arrays.sort(carArray,Car.carMakeComparator);
for(Car c : carArray)
{
System.out.print(c.getMake() + ",");
}
System.out.println();
System.out.print("Sorting by Model: ");
Arrays.sort(carArray,Car.carModelComparator);
for(Car c : carArray)
{
System.out.print(c.getModel() + ",");
}
System.out.println();
System.out.print("Sorting by Cost: ");
Arrays.sort(carArray,Car.carCostComparator);
for(Car c : carArray)
{
System.out.print(c.getCost() + ",");
}
}

}


No comments:

Post a Comment