One of the most common functions we need as developers dealing with data is sorting--by being able to sort our data, we can optimize our algorithms to run much faster, and find the data it needs to in a fraction of the time that it would take to otherwise.
As a quick thought experiment: imagine that you are searching for a name through a university’s roster. There may be tens of thousands of students at this school. If the roster you were given was not in alphabetical order, you would need to flip through every single page and look very carefully to make sure you didn’t skip a single name anywhere, until you finally find the name you are looking for. On the other hand, if the roster was alphabetized, not only do you have to be less rigorous in your search, but you could easily jump to the section in the roster with the same first letter, and continue to jump around pages in big leaps until you land upon the person you were looking for.
The more data you are working with, the more important it is that you are using it as effectively and efficiently as possible. In this article, we will go over how to sort any List implementation in Java (including ArrayList) using the Collections sort method.
You want to be able to print out the colors list, but in alphabetical order. How might you do this? Using java.util.Collections, sorting is as easy as a one-liner:
Ta-da! Your colors list has now been sorted in-place. If you were to print out the list, as such:
Then you would get the following output:
How easy was that?! It would be just as easy to use Collections.sort() to sort into ascending order a list of Integers, Floats, or any other simple data type for that matter. But what if you wanted to sort in descending order? There are definitely cases where this makes sense--imagine that you had a list of test scores for a certain class, and you wanted to figure out who the top-scoring students are. It would make much more sense to sort the list in descending order (highest scores first), so that the answers you are looking for are right at the top. Thankfully, Collections.sort()is overwritten with an optional 2nd parameter, which allows you to do just this:
But what’s a comparator? Well, a comparator is simply a function that compares two inputs and returns a number representing which input comes first. If you are sorting an ArrayList of primitive data types, then Java Collections already provides you with a reverseOrder() comparator. It can be called like this:
Now, colors have been reverse sorted in-place so that if you printed it out, you would get the following output:
In order to make our Color class compatible with Collections.sort(), so that Collections can understand how to compare and sort Color objects, we need to make two small modifications:
Notice that the Color’s compareTo method simply calls the String’s compareTo method; sorting will be done in alphabetical order. If we wanted to sort by red value in ascending order, for example, we could replace the return statement with return this.r - c.r; (if we wanted to sort by green value in descending order, it’d be return c.g - this.g;). Now, if we call
on an ArrayList of Colors rather than just Strings, it would work because Collections understands how to compare Color objects. If you do not want to make your object implement Comparable<Object>, you can alternatively write a comparator for your class, and pass that into the 2-parameter Collections.sort() method. A comparator overrides a method public int compare(Object one, Object two), and the Collections.sort() method uses this to compare objects while sorting. An example of SortByName and SortByRed comparators are implemented below:
With this, you can now call
without the Color class actually implementing Comparable, and it will still work. Sometimes, you will see this be done in-line, using lambda functions. A lambda function is essentially a nameless function that you can define within the line of code, which calls it. They are useful when you only need to call a function for one specific instance and don’t want to define a whole separate function elsewhere. The SortByName comparator could be defined in-line, using a lambda function, like this:
As you might have guessed, (a, b) represents the parameters of the lambda functions (the two objects to be compared). The -> signifies that what follows is a lambda function definition.
How to Sort an ArrayList in Java using the Java Collections.sort method
Let’s talk about Java Collections.sort method. The java.util package contains many useful utilities and packages which are often used by developers, including the ArrayList. Suppose you have the following simple program:You want to be able to print out the colors list, but in alphabetical order. How might you do this? Using java.util.Collections, sorting is as easy as a one-liner:
Ta-da! Your colors list has now been sorted in-place. If you were to print out the list, as such:
Then you would get the following output:
How easy was that?! It would be just as easy to use Collections.sort() to sort into ascending order a list of Integers, Floats, or any other simple data type for that matter. But what if you wanted to sort in descending order? There are definitely cases where this makes sense--imagine that you had a list of test scores for a certain class, and you wanted to figure out who the top-scoring students are. It would make much more sense to sort the list in descending order (highest scores first), so that the answers you are looking for are right at the top. Thankfully, Collections.sort()is overwritten with an optional 2nd parameter, which allows you to do just this:
But what’s a comparator? Well, a comparator is simply a function that compares two inputs and returns a number representing which input comes first. If you are sorting an ArrayList of primitive data types, then Java Collections already provides you with a reverseOrder() comparator. It can be called like this:
Now, colors have been reverse sorted in-place so that if you printed it out, you would get the following output:
How to use Collections to sort non-primitive data types in Java
So far, you’ve seen that sorting ArrayLists of strings or ints in Java using theCollections.sort()
method is as easy as one line of code. But oftentimes, your ArrayLists will be storing non-primitive data types. When you are working with data that has more complex attributes, you will want to write classes to represent these objects and how they will be compared to each other using their attributes. To explore an example of this, let’s revisit the example of sorting a list of colors, but this time, instead of sorting Strings, we will be sorting Color objects.
Our basic Color class might look something like this:
In order to make our Color class compatible with Collections.sort(), so that Collections can understand how to compare and sort Color objects, we need to make two small modifications:
- make Color a Comparable object (add implements Comparable<Object>)
- override the compareTo method in the class (override public int compareTo(Object o))
Notice that the Color’s compareTo method simply calls the String’s compareTo method; sorting will be done in alphabetical order. If we wanted to sort by red value in ascending order, for example, we could replace the return statement with return this.r - c.r; (if we wanted to sort by green value in descending order, it’d be return c.g - this.g;). Now, if we call
on an ArrayList of Colors rather than just Strings, it would work because Collections understands how to compare Color objects. If you do not want to make your object implement Comparable<Object>, you can alternatively write a comparator for your class, and pass that into the 2-parameter Collections.sort() method. A comparator overrides a method public int compare(Object one, Object two), and the Collections.sort() method uses this to compare objects while sorting. An example of SortByName and SortByRed comparators are implemented below:
With this, you can now call
without the Color class actually implementing Comparable, and it will still work. Sometimes, you will see this be done in-line, using lambda functions. A lambda function is essentially a nameless function that you can define within the line of code, which calls it. They are useful when you only need to call a function for one specific instance and don’t want to define a whole separate function elsewhere. The SortByName comparator could be defined in-line, using a lambda function, like this:
As you might have guessed, (a, b) represents the parameters of the lambda functions (the two objects to be compared). The -> signifies that what follows is a lambda function definition.
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.