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.
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
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 Arun.Singh
*
*/
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 couple of custom
* Comparators to sort object based upon 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);
}
}
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
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 Arun.Singh
*
*/
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 couple of custom
* Comparators to sort object based upon 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) Remember to use Collections.reverseOrder() comparator for sorting Object in reverse order or descending order, as shown in this example.
5) 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.
6) 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.
0 comments:
Post a Comment