Comparator and Comparable in Java

Comparator and Comparable are very useful for sorting the collection of objects in Java. Java provides some inbuilt methods to sort primitive types array or Wrapper classes array or list.

In this article, We will see what are the Comparator and Comparable interfaces. How to sort primitive /Wrapper data types using these interfaces. Then we will see how to sort the custom objects using these interfaces.

Comparable interface

Comparable interface present in java.lang package and contains only one method compareTo() method.

public int compareTo(Object obj);

this method returns -ve + ve and 0 as described below.

  • returns -ve if and only if obj1 has to come before obj2
  • returns +ve if and only if obj1 has to come after obj2
  • returns 0 if obj1 and obj2 are equal
package com.javacodestuffs.core.interfaces; public class ComparableExample2 { public static void main(String[] args) { System.out.println("A".compareTo("Z")); //-25 System.out.println("Z".compareTo("K")); //15 System.out.println("A".compareTo("A")); //0 /* System.out.println("A".compareTo(new Integer(10))); //Test.java:8: compareTo(java.lang.String) in java.lang.String cannot be applied to (java.lang.Integer) */ //System.out.println("A".compareTo(null));//NullPointerException } } output: -25 15 0

If we are depending on default natural sorting order then internally JVM will use compareTo() method to arrange objects in sorting order.

Now let’s try to sort an array of objects.

package com.javacodestuffs.core.interfaces; import java.util. * ; public class Bike implements Comparable < Bike > { private int id; private String name; private int engineCC; private double price; private String fuelType; public int getId() { return id; } public String getName() { return name; } public int getEngineCC() { return engineCC; } public double getPrice() { return price; } public String getFuelType() { return fuelType; } public Bike(int id, String name, int engineCC, double price, String fuelType) { this.id = id; this.name = name; this.engineCC = engineCC; this.price = price; this.fuelType = fuelType; } @Override public int compareTo(Bike bike) { return (this.id - bike.id); } @Override public String toString() { return "[id=" + this.id + ", name=" + this.name + ", engineCC=" + this.engineCC + ", price=" + this.price + ", fuelType=" + this.fuelType + "]"; } public static void main(String[] args) { Bike[] bikeArray = new Bike[6]; bikeArray[0] = new Bike(3, "Royal Enfield Classic 350", 346, 160000, "Petrol"); bikeArray[1] = new Bike(5, "JAWA 300", 296, 174000, "Petrol"); bikeArray[2] = new Bike(1, "Honda CB Shine", 124, 68112, "Petrol"); bikeArray[3] = new Bike(12, "KTM RC 200", 199, 196768, "Petrol"); bikeArray[4] = new Bike(7, "Yamaha FZ S V3.0 FI", 149, 101200, "Petrol"); bikeArray[5] = new Bike(2, "Hero Electric NYX", 48, 61866, "Electric"); //sorting Bikes array using Comparable interface implementation Arrays.sort(bikeArray); System.out.println("Default Sorting of Bikes :\n" + Arrays.toString(bikeArray)); } } output: Default Sorting of Bikes : [[id=1, name=Honda CB Shine, engineCC=124, price=68112.0, fuelType=Petrol], [id=2, name=Hero Electric NYX, engineCC=48, price=61866.0, fuelType=Electric], [id=3, name=Royal Enfield Classic 350, engineCC=346, price=160000.0, fuelType=Petrol], [id=5, name=JAWA 300, engineCC=296, price=174000.0, fuelType=Petrol], [id=7, name=Yamaha FZ S V3.0 FI, engineCC=149, price=101200.0, fuelType=Petrol], [id=12, name=KTM RC 200, engineCC=199, price=196768.0, fuelType=Petrol]]

Here Bikes array is sorted by id in ascending order.

In real life example, we need to sort the collection of objects based on different categories.

Java Comparator interface because Comparable.compareTo(Object o) method implementation can provide default sorting and we can’t change it dynamically. When we use Comparator, we can define multiple methods with different ways of sorting and then choose the sorting method based on our requirements.

Comparator

If we are not satisfied with default natural sorting order (or) if default natural sorting order is not available then we can define our own customized sorting by Comparator object.

Comparable meant for default natural sorting order.

Comparator meant for customized sorting order.

Comparator interface present in java.util package this interface defines the following 2 methods.

1). public int compare(Object obj1,Object Obj2);

  • returns -ve if and only if obj1 has to come before obj2
  • returns +ve if and only if obj1 has to come after obj2
  • returns 0 if obj1 and obj2 are equal

2). public boolean equals(Object obj);

Whenever we are implementing the Comparator interface we have to provide implementation only for compare() method. Implementing equals() method is optional because it is already available from Object class through inheritance.

Write a program to insert integer objects into the TreeSet where the sorting order is descending order.

package com.javacodestuffs.core.interfaces; import java.util.*; public class ComparatorExample1 { public static void main(String[] args) { TreeSet treeSet = new TreeSet(new MyComparator()); //line1 treeSet.add(101); treeSet.add(45); treeSet.add(29); treeSet.add(16); treeSet.add(62); System.out.println("The sorted treeset is : "); System.out.println(treeSet); } } class MyComparator implements Comparator { public int compare(Object obj1, Object obj2) { Integer i1 = (Integer) obj1; Integer i2 = (Integer) obj2; if (i1 < i2) return + 1; else if (i1 > i2) return - 100; else return 0; } } output: The sorted treeset is : [101, 62, 45, 29, 16]

At the line "1" if we are not passing the Comparator object then JVM will always call compareTo() method which is meant for default natural sorting order(ascending order)hence in this case the output. [16, 29, 45, 62, 101].

At the line "1" if we are passing Comparator object then JVM calls compare() method of MyComparator class which is meant for customized sorting order(descending order) hence in this case the output is [101, 62, 45, 29, 16]

Here is how we can create different Comparator implementation in the Bike class.

package com.javacodestuffs.core.interfaces; import java.util.* ; public class Bike implements Comparable < Bike > { private int id; private String name; private int engineCC; private double price; private String fuelType; public int getId() { return id; } public String getName() { return name; } public int getEngineCC() { return engineCC; } public double getPrice() { return price; } public String getFuelType() { return fuelType; } public Bike(int id, String name, int engineCC, double price, String fuelType) { this.id = id; this.name = name; this.engineCC = engineCC; this.price = price; this.fuelType = fuelType; } @Override public int compareTo(Bike bike) { return (this.id - bike.id); } @Override public String toString() { return "[id=" + this.id + ", name=" + this.name + ", engineCC=" + this.engineCC + ", price=" + this.price + ", fuelType=" + this.fuelType + "]"; } //sort Bike based on Price public static Comparator < Bike > priceComparator = new Comparator < Bike > () { @Override public int compare(Bike b1, Bike b2) { return (int)(b1.getPrice() - b2.getPrice()); } }; //sort Bike based on Name public static Comparator < Bike > nameComparator = new Comparator < Bike > () { @Override public int compare(Bike b1, Bike b2) { return b1.getName().compareTo(b2.getName()); } }; //sort Bike based on engineCC public static Comparator < Bike > engineCCComparator = new Comparator < Bike > () { @Override public int compare(Bike b1, Bike b2) { return (int)(b1.getEngineCC() - b2.getEngineCC()); } }; //sort Bike based on fuelType public static Comparator < Bike > fuelTypeComparator = new Comparator < Bike > () { @Override public int compare(Bike b1, Bike b2) { return b1.getFuelType().compareTo(b2.getFuelType()); } }; public static void main(String[] args) { Bike[] bikeArray = new Bike[6]; bikeArray[0] = new Bike(3, "Royal Enfield Classic 350", 346, 160000, "Petrol"); bikeArray[1] = new Bike(5, "JAWA 300", 296, 174000, "Petrol"); bikeArray[2] = new Bike(1, "Honda CB Shine", 124, 68112, "Petrol"); bikeArray[3] = new Bike(12, "KTM RC 200", 199, 196768, "Petrol"); bikeArray[4] = new Bike(7, "Yamaha FZ S V3.0 FI", 149, 101200, "Petrol"); bikeArray[5] = new Bike(7, "Bajaj Chetak", 48, 110000, "Electric"); //sort Bike array using Comparator by Price Arrays.sort(bikeArray, Bike.priceComparator); System.out.println("\nBikes list sorted by Price :\n" + Arrays.toString(bikeArray)); //sort Bike array using Comparator by fuelType Arrays.sort(bikeArray, Bike.fuelTypeComparator); System.out.println("\nBikes list sorted by fuelType:\n" + Arrays.toString(bikeArray)); //sort Bike array using Comparator by fuelType Arrays.sort(bikeArray, Bike.engineCCComparator); System.out.println("\nBikes list sorted by engineCCComparator:\n" + Arrays.toString(bikeArray)); //sort Bike array using Comparator by Name Arrays.sort(bikeArray, Bike.nameComparator); System.out.println("\nBikes list sorted by Name:\n" + Arrays.toString(bikeArray)); System.out.println("Default Sorting of Bikes :\n" + Arrays.toString(bikeArray)); } } output: Bikes list sorted by Price : [[id=1, name=Honda CB Shine, engineCC=124, price=68112.0, fuelType=Petrol], [id=7, name=Yamaha FZ S V3.0 FI, engineCC=149, price=101200.0, fuelType=Petrol], [id=7, name=Bajaj Chetak, engineCC=48, price=110000.0, fuelType=Electric], [id=3, name=Royal Enfield Classic 350, engineCC=346, price=160000.0, fuelType=Petrol], [id=5, name=JAWA 300, engineCC=296, price=174000.0, fuelType=Petrol], [id=12, name=KTM RC 200, engineCC=199, price=196768.0, fuelType=Petrol]] Bikes list sorted by fuelType: [[id=7, name=Bajaj Chetak, engineCC=48, price=110000.0, fuelType=Electric], [id=1, name=Honda CB Shine, engineCC=124, price=68112.0, fuelType=Petrol], [id=7, name=Yamaha FZ S V3.0 FI, engineCC=149, price=101200.0, fuelType=Petrol], [id=3, name=Royal Enfield Classic 350, engineCC=346, price=160000.0, fuelType=Petrol], [id=5, name=JAWA 300, engineCC=296, price=174000.0, fuelType=Petrol], [id=12, name=KTM RC 200, engineCC=199, price=196768.0, fuelType=Petrol]] Bikes list sorted by engineCCComparator: [[id=7, name=Bajaj Chetak, engineCC=48, price=110000.0, fuelType=Electric], [id=1, name=Honda CB Shine, engineCC=124, price=68112.0, fuelType=Petrol], [id=7, name=Yamaha FZ S V3.0 FI, engineCC=149, price=101200.0, fuelType=Petrol], [id=12, name=KTM RC 200, engineCC=199, price=196768.0, fuelType=Petrol], [id=5, name=JAWA 300, engineCC=296, price=174000.0, fuelType=Petrol], [id=3, name=Royal Enfield Classic 350, engineCC=346, price=160000.0, fuelType=Petrol]] Bikes list sorted by Name: [[id=7, name=Bajaj Chetak, engineCC=48, price=110000.0, fuelType=Electric], [id=1, name=Honda CB Shine, engineCC=124, price=68112.0, fuelType=Petrol], [id=5, name=JAWA 300, engineCC=296, price=174000.0, fuelType=Petrol], [id=12, name=KTM RC 200, engineCC=199, price=196768.0, fuelType=Petrol], [id=3, name=Royal Enfield Classic 350, engineCC=346, price=160000.0, fuelType=Petrol], [id=7, name=Yamaha FZ S V3.0 FI, engineCC=149, price=101200.0, fuelType=Petrol]] Default Sorting of Bikes : [[id=7, name=Bajaj Chetak, engineCC=48, price=110000.0, fuelType=Electric], [id=1, name=Honda CB Shine, engineCC=124, price=68112.0, fuelType=Petrol], [id=5, name=JAWA 300, engineCC=296, price=174000.0, fuelType=Petrol], [id=12, name=KTM RC 200, engineCC=199, price=196768.0, fuelType=Petrol], [id=3, name=Royal Enfield Classic 350, engineCC=346, price=160000.0, fuelType=Petrol], [id=7, name=Yamaha FZ S V3.0 FI, engineCC=149, price=101200.0, fuelType=Petrol]]

Comparable Comparator
1). We don’t need to make any code changes at the client side for using Comparable, Arrays.sort() or Collection.sort() methods automatically uses the compareTo() method of the class. For Comparator, the client needs to provide the Comparator class to use in compare() method
2). The comparable interface can be used to provide a single way of sorting. Comparator interface is used to provide different ways of sorting.
3). Comparable provides compareTo() method to sort elements. Comparator provides compare() method to sort elements.
4). Comparable is present in java.lang package. A Comparator is present in the java.util package.
5). We can sort the list elements of Comparable type by Collections.sort(List) method. We can sort the list elements of Comparator type by Collections.sort(List, Comparator) method.
6). For using Comparable, the Class needs to implement it.FFor using a Comparator we don’t need to make any change in the class.

Points to Remember regarding Comparable and Comparator

1). Comparable in Java is used to implement the natural ordering of objects. In Java API String, Date and wrapper classes implement Comparable interface. Its always good practice to override compareTo() for value objects.

2). If any class implement Comparable interface in Java then the collection of that object either List or Array can be sorted automatically by using Collections.sort() or Arrays.sort() method and object will be sorted based on there natural order defined by CompareTo method.

3). Objects which implement Comparable in Java can be used as keys in a SortedMap like a treemap or elements in a SortedSet for example TreeSet, without specifying any Comparator.

Post/Questions related to  Comparator and Comparable in Java

Comparator and Comparable in java interview questions
Comparator in java
A comparable example in java 8
Comparable vs comparable
Difference between comparator and comparable
Advantage of comparator over comparable
Java comparator example sort
How to sort HashSet in java using comparator?
How to sort set in java using comparator?
How to write generic comparators in java?
How to sort in descending order in java using comparator?
How to remove duplicate objects from ArrayList in java using comparator?
How to compare two integers in java using comparator?

In this article, we have seen the  Comparator and Comparable in Java with examples. All source code in the article can be found in the GitHub repository.