Thursday, October 25, 2012

How to sort Object in Java - Comparator and Comparable Example

Java Object Sorting Example
How do you sort list of Objects in Java is one of the frequently asked coding questions in Java interviews and surprisingly not every Java programmers know How sorting of object happens in Java. Comparator and Comparable interface along with Collections.sort() method is used to sort list of object in Java. compare() and compareTo() method of Comparator and Comparable interface provides comparison logic needed for sorting objects. compareTo() method is used to provide Object's natural order sorting and compare() method is used to sort Object with any arbitrary field. Almost all value classes in Java library e.g. String, Integer, Double, BigDecimal implement compareTo() to specify there natural sorting order. While overriding compareTo method String is sorted lexicographically and Integers are sorted numerically. Just beware that it must in consistent with equals method i.e. two objects which are equal by equals method in Java, compareTo() method must return zero for them.  Any way,  sorting standard value Object is not a problem for many Java programmer but some of them really struggle when it comes to sort custom Objects or domain Objects. In this Java sorting tutorial we will create custom object and sort list of Object in ascending and descending order.

Sorting list of Object in ascending and descending Order

How to sort list of Object in Java using Comparator and Comparable Example
Here is the list of steps we will follow in this Java sorting tutorial for creating custom Object, implementing Comparable or Comparator and finally sorting list of Object on ascending and descending order. Our knowledge of sorting ArrayList in ascending and descending order will come handy here.

1) Create Order object as custom or domain object
2) Implement Comparable and Comparator interface to define sorting logic
3) Sort list of Object using Collections.sort method



package test;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 *
 * Java program to test Object sorting in Java. This Java program
 * test Comparable and Comparator implementation provided by Order
 * class by sorting list of Order object in ascending and descending order.
 * Both in natural order using Comparable and custom Order using Comparator in Java
 *
 * @author http://java67.blogspot.com
 */

public class ObjectSortingExample {

    public static void main(String args[]) {
     
        //Creating Order object to demonstrate Sorting of Object in Java
        Order ord1 = new Order(101,2000, "Sony");
        Order ord2 = new Order(102,4000, "Hitachi");
        Order ord3 = new Order(103,6000, "Philips");
     
        //putting Objects into Collection to sort
        List<Order> orders = new ArrayList<Order>();
        orders.add(ord3);
        orders.add(ord1);
        orders.add(ord2);
     
        //printing unsorted collection
        System.out.println("Unsorted Collection : " + orders);
     
        //Sorting Order Object on natural order - ascending
        Collections.sort(orders);
     
        //printing sorted collection
        System.out.println("List of Order object sorted in natural order : " + orders);
     
        // Sorting object in descending order in Java
        Collections.sort(orders, Collections.reverseOrder());
        System.out.println("List of object sorted in descending order : " + orders);
             
        //Sorting object using Comparator in Java
        Collections.sort(orders, new Order.OrderByAmount());
        System.out.println("List of Order object sorted using Comparator - amount : " + orders);
     
        // Comparator sorting Example - Sorting based on customer
        Collections.sort(orders, new Order.OrderByCustomer());
        System.out.println("Collection of Orders sorted using Comparator - by customer : " + orders);
    }
}

/*
 * Order class is a domain object which implements
 * Comparable interface to provide sorting on natural order.
 * Order also provides copule of custom Comparators to
 * sort object based uopn amount and customer
 */

class Order implements Comparable<Order> {

    private int orderId;
    private int amount;
    private String customer;

    /*
     * Comparator implementation to Sort Order object based on Amount
     */

    public static class OrderByAmount implements Comparator<Order> {

        @Override
        public int compare(Order o1, Order o2) {
            return o1.amount > o2.amount ? 1 : (o1.amount < o2.amount ? -1 : 0);
        }
    }

    /*
     * Anohter implementation or Comparator interface to sort list of Order object
     * based upon customer name.
     */

    public static class OrderByCustomer implements Comparator<Order> {

        @Override
        public int compare(Order o1, Order o2) {
            return o1.customer.compareTo(o2.customer);
        }
    }

    public Order(int orderId, int amount, String customer) {
        this.orderId = orderId;
        this.amount = amount;
        this.customer = customer;
    }

 
    public int getAmount() {return amount; }
    public void setAmount(int amount) {this.amount = amount;}

    public String getCustomer() {return customer;}
    public void setCustomer(String customer) {this.customer = customer;}

    public int getOrderId() {return orderId;}
    public void setOrderId(int orderId) {this.orderId = orderId;}

    /*
     * Sorting on orderId is natural sorting for Order.
     */

    @Override
    public int compareTo(Order o) {
        return this.orderId > o.orderId ? 1 : (this.orderId < o.orderId ? -1 : 0);
    }
 
    /*
     * implementing toString method to print orderId of Order
     */

    @Override
    public String toString(){
        return String.valueOf(orderId);
    }
}

Output
Unsorted Collection : [103, 101, 102]
List of Order object sorted in natural order : [101, 102, 103]
List of object sorted in descending order : [103, 102, 101]
List of Order object sorted using Comparator - amount : [101, 102, 103]
Collection of Orders sorted using Comparator - by customer : [102, 103, 101]


Important points to note:

1) If you implement Comparable interface and override compareTo() method it must be consistent with equals() method i.e. for equal object by equals() method compareTo() must return zero. failing to so will affect contract of SortedSet e.g. TreeSet and SortedMap like TreeMap, which uses compareTo() method for checking equality

2) Some programmer use Integer subtraction to implement compareTo() in Java, which can cause overflow issue if both integers are not positive. See How compareTo works in Java for more details.

3) This example of sorting Object in Java also shows a good example of Where to use nested static class in Java. In this example We have created custom Comparator as static inner class, So that they can access properties of Order for comparison and also they are only used in context of Order class.

4) Don't forget to revise Difference between Comparator and Comparable in Java, which is one of the most asked Java questions on Interviews.

5) Remember to use Collections.reverseOrder() comparator for sorting Object in reverse order or descending order, as shown in this example.

6) Use Generics while implementing Comparator and Comparable interface, that's prevent error of accidentally overloading compareTo() and compare() method instead of overriding it, because both of these method accept Object as parameter. By using Generics and @Override annotation we effectively remove that subtle error.

7) This Object Sorting Exmaple in Java also teaches us Why you should override toString() in Java. If you are going to store your Object in Collection like List, Set or Map than printing Collection will call toString() method of each stored Object. By providing readable String format you can see What is stored in collection in logs. This is also a useful logging tips in Java.

That's all on How to sort list of Object in Java. It's upto you whether to use Comparable or Comparator interface for implementing sorting logic in Java.

Other Java Interview Questions you may find good

10 comments:

  1. Great example,thanks a lot

    ReplyDelete
  2. I am not able to understand if nested static class is used inside Order class,then why the static class is referenced through the outer class as Order.OrderbyAmount.
    As per my understanding,nested static class can be referenced through itself.

    ReplyDelete
  3. This was great, I learnt a lot from it. Thanks for sharing knowledge!

    ReplyDelete
  4. your code is wrong...

    try with this and pls find the answer why is this happening..in case of amount

    Order ord1 = new Order(101,600000000, "Sony");
    Order ord2 = new Order(102,4000, "Hitachi");
    Order ord3 = new Order(103,2000, "Philips");
    it should print
    List of Order object sorted using Comparator - amount : [101, 102, 103]
    but i am geting..

    List of Order object sorted using Comparator - amount : [103, 102, 101]
    Collection of Orders sorted using Comparator - by customer : [102, 103, 101]

    so please tell me how we get the required result.

    ReplyDelete
    Replies
    1. hi prakash ,

      above example is works fine ,may be in your code something wrong checkout condition which you apply.

      thanks
      chirag@india

      Delete
  5. Hi Chirag,

    NO,if i change the amount as

    Order ord1 = new Order(101,600000000, "Sony");
    Order ord2 = new Order(102,4000, "Hitachi");
    Order ord3 = new Order(103,2000, "Philips");

    then it wont give correct output.

    ReplyDelete
  6. How to get reverse order for the below

    Collections.sort(orders, new Order.OrderByAmount());

    ReplyDelete
  7. How to sort Hashmap based on values?

    ReplyDelete
  8. Simple example.....thanx

    ReplyDelete

Java67 Headline Animator