Different ways to sort an array in Java
By: Michael Tong
Tags: Java8, Sorting Algorithms, Java

Photo by Sarah Brown on Unsplash

In java, there are primary two ways to sort an array.

You can have a java class implements comparable and actually implement a compareTo method. That way, Arrays.sort will know exactly what algorithm it will count on to sort the array.

Or you can implement a comparator class that compare an object by name or by id. Afterward, in your client code you can do Arrays.sort, with the comparator as the second parameter.

Before we dive into comparable and comparator, let’s talk about how each of these two things work.

Comparable

Comparable is an interface that can be implemented by any java classes. It gives an object the compatibility to be compared to another object for sorting purposes.

Furthermore, the class that implements the comparable interface can customize the way sorting is done via implementing the compareTo method.

In fact, it is mandatory for the class that implements the comparable interface to implement the compareTo method.

Let’s take a look at the following class which implements comparable:

As you have noticed, when a class implements comparable, you also have to specify the generic. This generic will the type of objects/classes that comparable will be comparing against.

Inside the file, you also need to implement a compareTo method. This is where you decide on how you want your class objects to be sorted. In the scenario above, we want all the pairs to be sorted by endTime, ascending order, as dictated in the compareTo method.

What if the endTime is the same? We can also the do the following as well:

Over here, if the pair endTime is the same time then we can sort the pairs by their startTime in ascending order instead.

So far, we have shown how the class implementing comparable looks like. How does it look when the client actually have an array of pair and sorts them?

Let’s take a look:

While making a class implements comparable does give it the object class the ability to be sorted in the manner we want to when there is an array of them, it also couples a specific sorting behavior to every pair instance that’s out there. What if we want to sort certain pairs by endTime ascending and others by ending descending order? There’s no way to do that with the pair class implementing comparable.

Enter comparators.

Comparator is an interface that allows classes to sort objects of user defined classes. Instead of tightly coupling the sorting ability to the class itself, we are leaving the sorting logic to a comparator that specifically handles the logic of comparing two objects:

In here, PairComparatorByEndTime implements the Comparator interface and is required to implement the compare method instead. Similar to compareTo, the logic of sorting is determined over here.

In the client code, there is another overloaded arrays.sort method that takes in two parameters instead of one, the second one being a comparator instance.

With a comparator, the pair class no longer needs to implement the comparable and the comparator will do the sorting instead:

If desired, you can also include a different comparator to sort by start time instead.

What’s pros and cons of each approach?

With comparable, you can simply condense the sorting logic to the object class. You do not need to maintain different comparator classes outside to worry about how to sort the array/collection of objects.

However, this would only limit the object to be sorted in one manner and you cannot really sort two array/collection of objects differently. This can be an issue if you are using this for production code as you are scaling up your code.

With comparator, you give the client code several options to sort the array of class instances. This avoid the pitfall of using comparable and give more flexibility for users to sort the collection differently as needed.

However, there would be more code to maintain as there are extra logic for different comparator classes. Imagine having several comparators for all the classes you maintain. This can mean more testing and logic to maintain in the code base.

As a developer, it is really up to you to decide which solution to use depending on the scope of your problem.

That’s it! Happy coding!

If there are questions/concerns, feel free to comment in this article.