Comparable vs. Comparator in Java

Comparable and Comparator are two interfaces provided by Java Core API. From their names, we can tell they may be used for comparing stuff in some way. But what exactly are they and what is the difference between them? The following are two examples for answering this question. The simple examples compare two HDTV’s size. How to use Comparable vs. Comparator is obvious after reading the code.

1. Comparable

Comparable is implemented by a class in order to be able to comparing object of itself with some other objects. The class itself must implement the interface in order to be able to compare its instance(s). The method required for implementation is compareTo(). Here is an example:

class HDTV implements Comparable<HDTV> {
	private int size;
	private String brand;
 
	public HDTV(int size, String brand) {
		this.size = size;
		this.brand = brand;
	}
 
	public int getSize() {
		return size;
	}
 
	public void setSize(int size) {
		this.size = size;
	}
 
	public String getBrand() {
		return brand;
	}
 
	public void setBrand(String brand) {
		this.brand = brand;
	}
 
	@Override
	public int compareTo(HDTV tv) {
 
		if (this.getSize() > tv.getSize())
			return 1;
		else if (this.getSize() < tv.getSize())
			return -1;
		else
			return 0;
	}
}
 
public class Main {
	public static void main(String[] args) {
		HDTV tv1 = new HDTV(55, "Samsung");
		HDTV tv2 = new HDTV(60, "Sony");
 
		if (tv1.compareTo(tv2) > 0) {
			System.out.println(tv1.getBrand() + " is better.");
		} else {
			System.out.println(tv2.getBrand() + " is better.");
		}
	}
}
Sony is better.

2. Comparator

In some situations, you may not want to change a class and make it comparable. In such cases, Comparator can be used if you want to compare objects based on certain attributes/fields. For example, 2 persons can be compared based on `height` or `age` etc. (this can not be done using comparable.)

The method required to implement is compare(). Now let’s use another way to compare those TV by size. One common use of Comparator is sorting. Both Collections and Arrays classes provide a sort method which use a Comparator.

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
 
class HDTV {
	private int size;
	private String brand;
 
	public HDTV(int size, String brand) {
		this.size = size;
		this.brand = brand;
	}
 
	public int getSize() {
		return size;
	}
 
	public void setSize(int size) {
		this.size = size;
	}
 
	public String getBrand() {
		return brand;
	}
 
	public void setBrand(String brand) {
		this.brand = brand;
	}
}
 
class SizeComparator implements Comparator<HDTV> {
	@Override
	public int compare(HDTV tv1, HDTV tv2) {
		int tv1Size = tv1.getSize();
		int tv2Size = tv2.getSize();
 
		if (tv1Size > tv2Size) {
			return 1;
		} else if (tv1Size < tv2Size) {
			return -1;
		} else {
			return 0;
		}
	}
}
 
public class Main {
	public static void main(String[] args) {
		HDTV tv1 = new HDTV(55, "Samsung");
		HDTV tv2 = new HDTV(60, "Sony");
		HDTV tv3 = new HDTV(42, "Panasonic");
 
		ArrayList<HDTV> al = new ArrayList<HDTV>();
		al.add(tv1);
		al.add(tv2);
		al.add(tv3);
 
		Collections.sort(al, new SizeComparator());
		for (HDTV a : al) {
			System.out.println(a.getBrand());
		}
	}
}

Output:

Panasonic
Samsung
Sony

Often we may use Collections.reverseOrder() method to get a descending order Comparator. Like the following:

ArrayList<Integer> al = new ArrayList<Integer>();
al.add(3);
al.add(1);
al.add(2);
System.out.println(al);
Collections.sort(al);
System.out.println(al);
 
Comparator<Integer> comparator = Collections.reverseOrder();
Collections.sort(al,comparator);
System.out.println(al);

Output:

[3,1,2]
[1,2,3]
[3,2,1]

3. When to use Which?

In brief, a class that implements Comparable will be comparable, which means it instances can be compared with each other.

A class that implements Comparator will be used in mainly two situations: 1) It can be passed to a sort method, such as Collections.sort() or Arrays.sort(), to allow precise control over the sort order and 2) It can also be used to control the order of certain data structures, such as sorted sets (e.g. TreeSet) or sorted maps (e.g., TreeMap).

For example, to create a TreeSet. We can either pass the constructor a comparator or make the object class comparable.

Approach 1 – TreeSet(Comparator comparator)

class Dog {
	int size;
 
	Dog(int s) {
		size = s;
	}
}
 
class SizeComparator implements Comparator<Dog> {
	@Override
	public int compare(Dog d1, Dog d2) {
		return d1.size - d2.size;
	}
}
 
public class ImpComparable {
	public static void main(String[] args) {
		TreeSet<Dog> d = new TreeSet<Dog>(new SizeComparator()); // pass comparator
		d.add(new Dog(1));
		d.add(new Dog(2));
		d.add(new Dog(1));
	}
}

Approach 2 – Implement Comparable

class Dog implements Comparable<Dog>{
	int size;
 
	Dog(int s) {
		size = s;
	}
 
	@Override
	public int compareTo(Dog o) {
		return o.size - this.size;
	}
}
 
public class ImpComparable {
	public static void main(String[] args) {
		TreeSet<Dog> d = new TreeSet<Dog>();
		d.add(new Dog(1));
		d.add(new Dog(2));
		d.add(new Dog(1));
	}
}

References:
1. Comparable
2. Comparator

20 thoughts on “Comparable vs. Comparator in Java”

  1. TestArraylist.java
    ===================================
    package Compare;

    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Collections;

    import Util.TestUtil;
    /*
    * author:
    * date:
    * purpose:
    * Binary Search using collections
    *
    * */
    public class TestArraylist {

    /**
    * @param args
    */
    public static void main(String[] args) {
    // TODO Auto-generated method stub
    ArrayList ar=new ArrayList();
    ar.add(11);
    ar.add(22);
    ar.add(2);
    ar.add(23);
    ar.add(5);

    int searchval=23;
    // sorting List
    Collections.sort(ar);

    for(int arr:ar){
    System.out.print(“arrrr “+arr);
    }

    // method call
    int result=TestUtil.BinarySrchArrayList(ar,searchval);
    System.out.println(“result outside “+result);

    if(result>=0){
    System.out.println(“result “+result);
    }
    else{
    System.out.println(“result Not exist “);
    }

    }

    }

    TestComparableSrch.java
    ============================
    package Compare;

    import java.util.ArrayList;
    import java.util.Collections;

    import Util.TestUtil;
    /*
    * author:
    * date:
    * purpose:
    * Binary Search using comparable
    *
    * */
    public class TestComparableSrch {

    /**
    * @param args
    */
    public static void main(String[] args) {
    // TODO Auto-generated method stub

    int searchval=2;
    EmployeeComp e1= new EmployeeComp(4, “john”, 24);
    EmployeeComp e2= new EmployeeComp(3, “muir”, 20);
    EmployeeComp e3= new EmployeeComp(5, “rose”, 21);
    EmployeeComp e4= new EmployeeComp(1, “victor”, 22);

    ArrayList arrlist=new ArrayList();
    arrlist.add(e1);
    arrlist.add(e2);
    arrlist.add(e3);
    arrlist.add(e4);

    // sorting
    Collections.sort(arrlist);

    for(EmployeeComp e:arrlist){
    System.out.println(“eeee “+e.getEmpName());
    }
    String result=TestUtil.BinaryComparableArrayList(arrlist,searchval);
    System.out.println(“result “+result);

    }

    }

    TestComparatorSrch.java
    ======================================
    package Compare;

    import java.util.ArrayList;
    import java.util.Collections;

    import Util.TestUtil;
    /*
    * author:
    * date:
    * purpose:
    * Binary Search using comparator
    *
    * */
    public class TestComparatorSrch {

    /**
    * @param args
    */
    public static void main(String[] args) {
    // TODO Auto-generated method stub

    String searchval=”muirs”;
    EmployeeComparator e1= new EmployeeComparator(4, “john”, 24);
    EmployeeComparator e2= new EmployeeComparator(3, “rose”, 20);
    EmployeeComparator e3= new EmployeeComparator(5, “muir”, 21);
    EmployeeComparator e4= new EmployeeComparator(1, “victor”, 22);

    ArrayList arrlist=new ArrayList();
    arrlist.add(e1);
    arrlist.add(e2);
    arrlist.add(e3);
    arrlist.add(e4);

    // sorting
    Collections.sort(arrlist,new EmployeeComparator());
    for(EmployeeComparator e:arrlist){
    System.out.println(“eeee “+e.getEmpName());
    }
    String result=TestUtil.BinaryComparatorArrayList(arrlist,searchval);
    System.out.println(“result “+result);

    }

    }

  2. TestUtil.java
    ====================
    package Util;
    import java.util.ArrayList;
    import Compare.EmployeeComp;
    import Compare.EmployeeComparator;
    //Util method for the business logic
    public class TestUtil {
    static int RecordNotExist=-1;
    public static int BinarySrchArray(int[]arr,int searchval){
    //System.out.println(“searchval”+searchval);
    if(arr!=null){
    //System.out.println(“arr.length”+arr.length);
    int low=0;
    int high=arr.length-1;
    int mid=(low+high)/2;
    int out;

    while(low<=high){
    if(arr[mid]==searchval){
    //System.out.println("hi "+searchval);
    out=arr[mid];
    return mid;
    }
    else if(arr[mid]<searchval){

    low=mid+1;
    }
    else{
    high=mid-1;
    }
    mid=(low+high)/2;

    }

    }

    return RecordNotExist;

    }

    //arraylist
    public static int BinarySrchArrayList(ArrayList arr,int searchval){
    //System.out.println(“searchval”+searchval);
    if(arr!=null){
    //System.out.println(“arr.length”+arr.length);
    int low=0;
    int high=arr.size()-1;
    int mid=(low+high)/2;
    int out;

    while(low<=high){
    if(arr.get(mid)==searchval){
    //System.out.println("hi "+searchval);
    out=arr.get(mid);
    return mid;
    }
    else if(arr.get(mid)<searchval){

    low=mid+1;
    }
    else{
    high=mid-1;
    }
    mid=(low+high)/2;

    }

    }

    return RecordNotExist;

    }

    // comparable

    public static String BinaryComparableArrayList(ArrayList arr,int searchval){
    //System.out.println(“searchval”+searchval);
    if(arr!=null){
    //System.out.println(“arr.length”+arr.length);
    int low=0;
    int high=arr.size()-1;
    int mid=(low+high)/2;
    int out;

    while(low<=high){
    if(arr.get(mid).getEmpId()==searchval){
    //System.out.println("hi "+searchval);
    out=arr.get(mid).getEmpId();
    return arr.get(mid).getEmpName();
    }
    else if(arr.get(mid).getEmpId()<searchval){

    low=mid+1;
    }
    else{
    high=mid-1;
    }
    mid=(low+high)/2;

    }

    }

    return "RecordNotExist";

    }
    //Comparator

    public static String BinaryComparatorArrayList(ArrayList arr,String searchval){
    //System.out.println(“searchval”+searchval);
    if(arr!=null){
    //System.out.println(“arr.length”+arr.length);
    int low=0;
    int high=arr.size()-1;
    int mid=(low+high)/2;
    int out;

    while(low<=high){
    if(arr.get(mid).getEmpName().equals(searchval)){
    //System.out.println("hi "+searchval);
    out=arr.get(mid).getEmpId();
    System.out.println("hi "+out);
    return arr.get(mid).getEmpName();
    }
    else if(arr.get(mid).getEmpName().compareTo(searchval)<0){

    low=mid+1;
    }
    else{
    high=mid-1;
    }
    mid=(low+high)/2;

    }

    }

    return "NameNotExist";

    }
    }

    EmployeeComp.java
    ============================
    package Compare;
    /*
    * author:
    * date:
    * purpose:
    * Implementation using comparable interface for sorting employee objects
    *
    * */
    public class EmployeeComp implements Comparable {

    private int empId;
    private String empName;
    private int age;

    public EmployeeComp(int id,String name,int age){
    this.empId=id;
    this.empName=name;
    this.age=age;
    }

    public int getEmpId() {
    return empId;
    }

    public void setEmpId(int empId) {
    this.empId = empId;
    }

    public String getEmpName() {
    return empName;
    }

    public void setEmpName(String empName) {
    this.empName = empName;
    }

    public int getAge() {
    return age;
    }

    public void setAge(int age) {
    this.age = age;
    }

    @Override
    public int compareTo(EmployeeComp o) {
    // TODO Auto-generated method stub
    return this.empId-o.empId;
    }

    }

    EmployeeComparator.java
    ==============================
    package Compare;

    import java.util.Comparator;
    /*
    * author:
    * date:
    * purpose:
    * Implementation using comparator interface for sorting employee objects
    *
    * */
    public class EmployeeComparator implements Comparator {

    private int empId;
    private String empName;
    private int age;

    public EmployeeComparator(){

    }

    public EmployeeComparator(int id,String name,int age){
    this.empId=id;
    this.empName=name;
    this.age=age;
    }

    public int getEmpId() {
    return empId;
    }
    public void setEmpId(int empId) {
    this.empId = empId;
    }
    public String getEmpName() {
    return empName;
    }
    public void setEmpName(String empName) {
    this.empName = empName;
    }
    public int getAge() {
    return age;
    }
    public void setAge(int age) {
    this.age = age;
    }
    @Override
    public int compare(EmployeeComparator object1, EmployeeComparator object2) {
    // TODO Auto-generated method stub
    return object1.getEmpName().compareTo(object2.getEmpName());
    }

    }

    TestBinaryArraySearch:
    ================================
    package Compare;

    import java.util.Arrays;

    import Util.TestUtil;
    /*
    * author:
    * date:
    * purpose:
    * Binary search using Arrays
    *
    * */
    public class TestBinaryArraySearch {

    /**
    * @param args
    */
    public static void main(String[] args) {
    // TODO Auto-generated method stub

    int [] arr={1,22,6,3,9};
    int searchval=1;
    // sorting array
    Arrays.sort(arr);
    for(int i=0;i=0){
    System.out.println(“result “+result);
    }
    else{
    System.out.println(“result Not exist “);
    }

    }

    }

  3. As approach #3, we can implement the comparator as an anonymous class for the treemap. Its more reasonable if the only place we will use the comparator is one time only.
    TreeSet d = new TreeSet(new Comparator(){
    @Override
    public int compare(Dog d1, Dog d2) {
    return d1.size – d2.size;
    }
    });

  4. we can add comparator logic with ananymous method way ..

    package com.venu.comparator;

    import java.util.*;

    import java.io.*;

    class Simple{

    public static void main(String args[]){

    ArrayList al=new ArrayList();

    al.add(new Student(101,”Vijay”,23));

    al.add(new Student(106,”Ajay”,27));

    al.add(new Student(105,”Jai”,21));

    System.out.println(“Sorting by Name…”);

    Collections.sort(al,new Comparator() {

    @Override

    public int compare(Student o1, Student o2) {

    // TODO Auto-generated method stub

    return o1.name.compareTo(o2.name);

    }

    });

    Iterator abs = al.iterator();

    while(abs.hasNext()){

    Student x = (Student) abs.next();

    System.out.println(“the values ” + x.age + “the names” + x.name + “the roll no” + x.rollno);

    }

    Collections.sort(al,new Comparator() {

    @Override

    public int compare(Student o1, Student o2) {

    // TODO Auto-generated method stub

    if(o1.age == o2.age)

    return 0;

    else if(o1.age >o2.age)

    return 1;

    else

    return -1;

    }

    });

    Iterator agecmp = al.iterator();

    while(agecmp.hasNext()){

    Student x = (Student) agecmp.next();

    System.out.println(x.rollno+” “+x.name+” “+x.age);

    }

    }

    }

    //POJO Class

    package com.venu.comparator;
    class Student{
    int rollno;
    String name;
    int age;

    public int getRollno() {
    return rollno;
    }

    public void setRollno(int rollno) {
    this.rollno = rollno;
    }

    public String getName() {
    return name;
    }

    public void setName(String name) {
    this.name = name;
    }

    public int getAge() {
    return age;
    }

    public void setAge(int age) {
    this.age = age;
    }

    Student(int rollno,String name,int age){
    this.rollno=rollno;
    this.name=name;
    this.age=age;
    }

    }

  5. What I feel, that when you are creating new class and which needs to be sorted or compared, it should be implemented by Comparable and if we have some pre-developed class and need to add functinality for compare or sorting, then we need to create a class implemented by Comprator and use this class as a parameter in sort method.

  6. hi and one more doubt is Collections.sort(al, new SizeComparator());
    what is this actually doing
    my guess sizecomparatorobject.compare(obj1 of al,obj2 of al)
    by the use of result returned by the above compare method (i.e)1,-1,0 how sorting will be done?

  7. hi my doubt about this tutorial is

    why we are going for comparator/comparable interface? it is possible for us to define such comparision method inside our class and can call it by the use of instance of its own.

    class SizeComparator implements Comparator {
    @Override
    public int compare(HDTV tv1, HDTV tv2) {
    int tv1Size = tv1.getSize();
    int tv2Size = tv2.getSize();

    if (tv1Size > tv2Size) {
    return 1;
    } else if (tv1Size < tv2Size) {
    return -1;
    } else {
    return 0;
    }
    }
    }
    instead of this it is possible to have our own method?

  8. Under Heading 2.Comparator
    “Comparator is capable of comparing two DIFFERENT types of objects.”
    EDIT: Comparator is capable if comparing objects based on different attributes. e.g. 2 men can be compared based on `name` or `age` etc. (this can not be done using comparable. ) Even in the example shown above, author provides example where object of SAME type (HDTV) is being used.

Leave a Comment