Sorting Collections with Java Streams API

Examples of sorting various Java collections using Java Streams API sorted() method.

Overview

Java Streams API provides a flexible and readable way to iterate through collection elements and perform various operations on the elements. In this tutorial we’ll explore the sorted() method of Steams. We will have an overview of this method and use it to sort different Java collections. Also, we will explore way of providing custom sort logic, or sorting collections in reversed order.

To learn more about Java Streams, please read – Java Streams API Guide.

Java Streams sorted() Method

Java Streams API provides sorted() method that is used for sorting the elements in the stream. The sorted() method is a Streams Intermediate Operation method and that comes in two flavours.

Java Streams sorted()

This method does not take any arguments and it sorts the elements in the given stream according to their natural order, and returns a new stream instance.

Stream<T> sorted();
Code language: Java (java)

It is important to note that, in order to use this method for sorting the elements in the stream must be Comparable. If the elements in the streams do not implement Comparable, then the method may throw ClassCastException.

Java Streams sorted(Comparator)

On the other hand the other flavour of this method accepts a Comparator instance. This method sorts elements in the given stream according to the provided Comparator implementation.

Stream<T> sorted(Comparator<? super T> comparator);
Code language: Java (java)

We can use Comparators to sort collections when we want to keep the comparison logic of out the objects.

Sorting a Stream of Elements

Let’s use Java Streams and Streams#sorted() method to sort a collection in the natural order of their elements. Before that, let’s consider we have a Student class like this.

public class Student { private final Long studentId; private final String firstName; private final String lastName; private final Integer age; //Constructors, Getter, and Setter methods }
Code language: Java (java)

Let’s create a few dummy students and put them in a Collection.

Student student1 = new Student(2L, "Karl", "A", 18); Student student2 = new Student(3L, "Jack", "P", 20); Student student3 = new Student(5L, "Nick", "G", 17); Student student4 = new Student(1L, "Tom", "A", 22); Student student5 = new Student(4L, "Jon", "E", 22); Collection<Student> students = new HashSet<>(); students.add(student1); students.add(student2); students.add(student3); students.add(student4); students.add(student5);
Code language: Java (java)

Note that, we have created an HashSet of student instances. However, you may use any other collection implementation as well.

Let’s sort the first name of the students in their natural form, i.e. in alphabetical order.

List<String> firstNames = students.stream() .map(Student::getFirstName) .sorted() .collect(Collectors.toList());
Code language: Java (java)

Firstly, we have created a stream of Student instances and then created a stream of first names of the students. Next, we used sorted() method on the stream of Strings and collected them in a list.

[Jack, Jon, Karl, Nick, Tom]

As expected the first names of the students are sorted. Remember that, this method worked because like other Java data types String also implements Comparable. Thus, we did not need to provide a Comparator.

Sorting a Stream of Custom Objects

Using Java Streams, we can also sort a Stream of custom elements, for example a stream of our Student objects. However our custom object does not implement Comparable. Thus, we need to provide our own comparison logic in the form of a Comparator.

List<Student> firstNames = students.stream() .sorted(Comparator.comparing(Student::getFirstName)) .collect(Collectors.toList());
Code language: Java (java)

Here, we are using Java Lambda expression based Comparator implementation to sort a collection of objects. In the end we are collecting the sorted objects a List.

Student(studentId=3, firstName=Jack, lastName=P, age=20)
Student(studentId=4, firstName=Jon, lastName=E, age=22)
Student(studentId=2, firstName=Karl, lastName=A, age=18)
Student(studentId=5, firstName=Nick, lastName=G, age=17)
Student(studentId=1, firstName=Tom, lastName=A, age=22)

As the output denotes our Student collection is now sorted based the first name.

Reverse Sorting with Java Streams

By default, both of the Java Stream sorted() methods sort the elements in the forward or ascending order. To sort a stream in the descending order of the elements, we need to provide a reverse Comparator.

For example, let’s sort a stream of elements in the descending natural order.

List<String> firstNames = students.stream() .map(Student::getFirstName) .sorted(Comparator.reverseOrder()) .collect(Collectors.toList());
Code language: Java (java)

Passing a reversed comparator, we can reverse the natural sort order. The same is evident from the output.

[Tom, Nick, Karl, Jon, Jack]

Similarly, we can sort a collection of custom objects in reverse order. To do that, we need to chose a reversed Comparator.

List<Student> firstNames = students.stream() .sorted(Comparator.comparing(Student::getFirstName).reversed()) .collect(Collectors.toList());
Code language: Java (java)

And the results will be in the descending order of the student’s first name.

Sorting a Stream of Map

Similar to any Collection, we can also use Java Steams API to sort Java Map. We will quickly see code examples of doing that here. If you are interested more on Sorting Java HashMaps, consider reading – Sort Java HashMap by Key or by Value.

Sort based on the key

List<Long> studentIds = studentMap.keySet().stream() .sorted() .collect(Collectors.toList());
Code language: Java (java)

Here, we are extracting set of all keys from the map and creating stream from it. Thus, the stream it generates is a stream of Long values. That is why, we can simply sort the elements using natural order.

Alternatively, let’s see sorting based on the Value.

List<Student> studentIds = studentMap.values().stream() .sorted(Comparator.comparing(Student::getFirstName)) .collect(Collectors.toList());
Code language: PHP (php)

We are creating a stream of values, i.e. Students and using a Comparator to sort based on the first name.

Summary

This was a quick tutorial on using Java Streams sorted() method. We first, understood the two forms of this method. First form, can sort elements in the stream by their natural order. However, to do so the elements must be of Comparable type. Else, the sorted() method throws ClassCastException.

The second of of the sorted() method accepts a Comparator, where we can plugin our own comparison logic. This method is useful to sort objects that are not Comparable. Also, we learned to change the sorting order of the elements to achieve descending order.

For full source of the examples used here, please visit our Github Repository.