How to implement collection ordering?

SortedSet and SortedMap interfaces maintain sorted order. The classes, which implement the Comparable interface, impose natural order. By implementing Comparable, sorting an array of objects or a collection (List etc) is as simple as:

Arrays.sort(myArray);
Collections.sort(myCollection); // do not confuse “Collections” utility class with the
// “Collection” interface without an “s”.

For classes that don’t implement Comparable interface, or when one needs even more control over ordering based on multiple attributes, a Comparator interface should be used.

Comparable interface Comparator interface
The “Comparable” allows itself to compare with another similar object (i.e. A class that implements Comparable becomes an object to be compared with). The method compareTo() is specified in the interface. The Comparator is used to compare two different objects. The following method is specified in the Comparator interface.
public int compare(Object o1, Object o2)
Many of the standard classes in the Java library like String, Integer, Date, File etc implement the Comparable interface to give the class a “Natural Ordering”. For example String class uses the following methods:
public int compareTo(o)
public int compareToIgnoreCase(str)

You could also implement your own method in your own class as shown below:
…imports
public class Pet implements Comparable {
int petId;
String petType;
public Pet(int argPetId, String argPetType) {
petId = argPetId;
this.petType = argPetType;
}
public int compareTo(Object o) {
Pet petAnother = (Pet)o;
//natural alphabetical ordering by type
//if equal returns 0, if greater returns +ve int,
//if less returns -ve int
return this.petType.compareTo(petAnother.petType);
}
public static void main(String[] args) {
List list = new ArrayList();
list.add(new Pet(2, “Dog”));
list.add(new Pet(1, “Parrot”));
list.add(new Pet(2, “Cat”));
Collections.sort(list); // sorts using compareTo method
for (Iterator iter = list.iterator(); iter.hasNext();) {
Pet element = (Pet) iter.next();
System.out.println(element);
}
}
public String toString() {
return petType;
}
}

Output: Cat, Dog, Parrot
You can have more control by writing your Comparator class. Let us write a Comparator for the Pet class shown on the left. For most cases natural ordering is fine as shown on the left but say we require a special scenario where we need to first sort by the “petId” and then by the “petType”. We can achieve this by writing a “Comparator” class.
…imports
public class PetComparator implements Comparator, Serializable{
public int compare(Object o1, Object o2) {
int result = 0;
Pet pet = (Pet)o1;
Pet petAnother = (Pet)o2;
//use Integer class’s natural ordering
Integer pId = new Integer(pet.getPetId());
Integer pAnotherId = new Integer(petAnother.getPetId());
result = pId.compareTo(pAnotherId);
//if ids are same compare by petType
if(result == 0) {
result= pet.getPetType().compareTo
(petAnother.getPetType());
}
return result;
}
public static void main(String[] args) {
List list = new ArrayList();
list.add(new Pet(2, “Dog”));
list.add(new Pet(1, “Parrot”));
list.add(new Pet(2, “Cat”));
Collections.sort(list, new PetComparator());
for (Iterator iter = list.iterator(); iter.hasNext();){
Pet element = (Pet) iter.next();
System.out.println(element);
}
}
}

Output: Parrot, Cat, Dog.
Note: some methods are not shown for brevity.

Important : The ordering imposed by a java.util.Comparator “myComp” on a set of elements “mySet” should be consistent with equals() method, which means for example:

if compare(o1,o2) == 0 then o1.equals(o2) should be true.
if compare(o1,o2) != 0 then o1.equals(o2) should be false.

If a comparator “myComp” on a set of elements “mySet” is inconsistent with equals() method, then SortedSet or SortedMap will behave strangely and is hard to debug. For example if you add two objects o1, o2 to a TreeSet (implements SortedSet) such that o1.equals(o2) == true and compare(o1,o2) != 0 the second add operation will return
false and will not be added to your set because o1 and o2 are equivalent from the TreeSet’s perspective.
TIP : It is always a good practice and highly recommended to keep the Java API documentation handy and refer to it as required while coding. Please refer to java.util.Comparator interface API for further details.

Tagged . Bookmark the permalink.

Leave a Reply