When it comes to the case that we have to sort a list of objects according to custom-defined criteria, Collections.sort() serves this situation very well and flexibly.
Quick view
Java Collections class provides us with a very convenient method Collections.sort() to sort all List implementations such as LinkedList and ArrayList.
There are two overloaded Collections.sort() methods, which are:
sort(List list): Sorts the elements of the List in ascending order of their natural ordering.
sort(List list, Comparator c): Sorts the elements of the list according to the order induced by the comparator.
Sort(List list) - with no Comparable interface
Take an ArrayList of String as an example:
Then, try to sort it using Collections.sort() or List.sort():
The result will be:
[BMW, Ferrari, Lamborghini, Mc Laren]
Hence, we can see that Collections.sort() has sorted the list of String in Lexical order. And it does not return anything.
But how about sorting a list of custom objects? It can be solved flexibly as well.
Consider a class Car:
Create a list of Cars:
In order to sort this list, if we directly use the Collections.sort(List list), it will give a Compile Time Error because there is no natural ordering defined for the Car objects. So, it doesn’t know how to sort this list.
For objects to have a natural order they must implement the interface Comparable.
Sort(List list) - with Comparable interface
The Comparable interface has a method compareTo(), which returns a negative, 0, a positive if the current value is less than, equal to, or greater than the value we are comparing with, respectively.
Let’s enhance the Car class to implement Comparable interface. We are defining that the natural order of sorting is based on the “id” field of Car:
So it's now implemented with Comparable, we can sort list without any errors:
The output will be as below - sort by id (1, 2, 3, 4):
1 BMW S1000 RR
2 Mc Laren 720S
3 Ferrari F90
4 Lamborghini Aventador
Sort(List list, Comparator c)
In order to define a custom logic for sorting, which is different from the natural ordering of the elements, we can implement the Comparator interface and pass an instance of it as the second argument of sort().
Let’s consider that we want to define the ordering based on the “brand” field of the Car. We implement the Comparator, and in its compare() method, we need to write the logic for comparison:
Now, we can sort it using this comparator:
The output will be as below:
1 BMW S1000 RR
3 Ferrari F90
4 Lamborghini Aventador
2 Mc Laren 720S
Instead of writing a new class for Comparator, using lambda function, we can provide sorting logic at runtime as well:
My example
Given that we have a list of cars like this:
What if I want to sort with custom criteria combined of many fields related to different priorities? Brand is the first priority to compare, if cars have the same Brand, then it will use Model to compare.
The example below is the Comparator in ascending order:
Next, we just implement a function to call the Comparator.
Then, we can use this function anywhere we want to sort a list with custom conditions:
The result will be:
3 BMW i8
1 BMW S1000 RR
4 Lamborghini Aventador
2 Mc Laren 720S
Reverse the order
Collections provides an extremely friendly built-in method to support the reversing of the order of the list. And here is how it was used:
reverseOrder(): Returns a Comparator that imposes the reverse of natural ordering of elements of the collection.
reverseOrder(Comparator cmp): Returns a Comparator that imposes reverse ordering of the specified comparator.
Example:
Collections.sort(carList, Collections.reverseOrder());
carList.sort(Collections.reverseOrder())
Collections.sort(carList, Collections.reverseOrder(new SortByBrand()));
sortCarsByBrandModel(carList, Collections.reverseOrder());
コメント