Different ways of Sorting in Java
Introduction
As we know Java is an Object-oriented Programming Language, and it has primitive(int, char, long) and non-primitive (String, Integer, custom Objects) data types, So whenever we work with data types object sorting is always an important requirement, Like most of the time we need to sort the elements so we think how to sort which method to use, So in this post, I am going to explain different ways of sorting Objects in Java.
Basically in Java, there are two classes which have a sort method.
1. Arrays
2. Collections
The arrays class method is used for sorting elements of primitive types, and in this stability(order of joining the array) is not required. It internally uses Double Pivot Quick Sort. It does not sort arrays other than the natural order.
public static void sortPrimitiveArray() {
int[] arr = {10,8,7, 12, 5};
//sort
Arrays.sort(arr);
//print
System.out.println(Arrays.toString(arr));
}
The collections class sort method is used by the classes which implement the List interface, like ArrayList, LinkedList, and Vector, It internally uses merge sort, and stability is required here.
So one doubt could be then If we have a Set like HashSet or LinkedHashSet, then how to sort them?
The answer for the above is: First convert your Set into a List and then sort because we do not have a sort method for Set.
Apart from the natural order, we can sort in reverse order also.
Collections Sort Methods
sort(List<T> list) = It takes a list and sorts it as per natural order.
sort(List<T> list, Comparator c) = It sorts the element as per the comparator provided.
Like List<String> can get sorted without using Comparable or Comparator
If we use List<Employee> then we need Comparable or Comparator because there is no natural ordering defined for custom Objects.
List<String> empName = new ArrayList<>();
empName.add("Mohan");
empName.add("Bob");
empName.add("jack");
Collections.sort(empName);
System.out.println(empName);
[Bob, Mohan, jack]
Sorting with Comparable
If we create an Employee class like this:
public class Employee {
private int id;
private String name;
private int age;
public Employee(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
public static void main(String[] args) {
List<Employee> emps = new ArrayList<>();
emps.add(new Employee(1, "mohan", 22));
emps.add(new Employee(2, "bob", 24));
emps.add(new Employee(3, "Test", 34));
//we will be getting compile time error in this line becasue Employee is a custome
//Object and it needs to use Comparable or Comparator.
//So if we add Comparable this error will be removed.
Collections.sort(emps);
}
}
So if we change the first line like below and implement the compareTo method then the compile-time error will go, but if we do not provide any logic inside the compareTo method it will not sort the list.
public class Employee implements Comparable<Object>{
@Override
public int compareTo(Object o) {
Employee e = (Employee) o;
//for reverse order based on id
//return e.getId() - this.getId();
//for natural order based on id
//return this.getId() - e.getId();
//sort string properties in reverse order lexographically
return e.getName().compareTo(this.getName());
}
Collections.reverseOrder() = This method itself returns a comparator which we can pass in the sort method for doing reverse of natural ordering.
Collections.sort(al, Collections.reverseOrder());
There are some limitations to using comparable like there can be only single field comparison (we can use libraries, or it will be complex to make multi fields), and it modifies the same class also so to make it more cleaner and better we should use Comparators.
Sorting with Comparator
So while using comparable we found out there are some limitations, so to overcome that we should use Comparator, whenever the requirement is like we want to do multi-field sorting or don’t want to include compareTo logic in the POJO class itself or there is some flexible requirement.
Comparator is present in java.util package.
One way to use a comparator is :
Collections.sort(emps, new Comparator<Employee>() {
@Override
public int compare(Employee o1, Employee o2) {
return o1.getId() - o2.getId();
}
});
emps.forEach(e -> System.out.println(e.getId()));
We can make this code concise by using lambda:
Collections.sort(emps, (o1, o2) -> o1.getId() - o2.getId());
//more short
Collections.sort(emps, Comparator.naturalOrder());
Sort using multiple Comparators, In Java 8 there is a method for making the chain of comparators and we can use that like below:
Collections.sort(emps, new NameComparator().thenComparing(new AgeComparator()));
emps.forEach(e -> System.out.println(e.getName()+ " "+e.getAge()));
Apart from that if we want to sort objects using multiple fields we can use Guava or Apache commons library for making it better grouping.
Sorting of Map:
For sorting a map in Java either by key or value, we should use TreeMap which does the sorting in natural order just by converting the hashMap into treemap.
Apart from that, we can pass a custom comparator while creating a tree Map and that can do sorting by keys.
If we sort the map by values then we can use a linked list and tree map both.
If any suggestions please let me know in the comments below.
For further implementations and more such posts please follow and clap!!
Thanks for reading!!
Connect with me on LinkedIn