4.5.  Sort a collection by using lambda expressions

[Note]
  • blah

Java streams API has several sorting methods.

Below example shows the stream of employees is mapped to the employee names and then there is a sorted() method, which returns the sorted stream of employee names. Remember, the sorted() method does not take any parameter here, and hence it will sort the list in natural order.

public class Employee {
    public String name;

    public Employee(String n) {
        name = n;
    }
}
					


Stream<Employee> emps = Stream.of(new Employee("John"), new Employee("Jane"), new Employee("Jack"));
List<String> sl = emps
    .map(e -> e.name)
    .sorted()
    .collect(Collectors.toList());
System.out.println(sl);

					

Output:

[Jack, Jane, John]
					

[Important]

The Stream.sorted() method without parameters requires a stream of Comparable elements!

If the elements of this stream are not Comparable, a java.lang.ClassCastException may be thrown when the terminal operation is executed.

Here is how can we provide our own sorting logic by using sorted(...) and providing a Comparator interface. The comparing(...) and few other useful methods have been added to the Comparator. Here is an example how the comparing(...) method is used to provide a custom sorting logic.

public class Employee {
    public String name;

    public Employee(String n) {
        name = n;
    }

    @Override
    public String toString() {
        return name;
    }
}
					


Stream<Employee> emps = Stream.of(new Employee("Nathaniel"), new Employee("Steve"), new Employee("Nick"));
List<Employee> sl = emps
    .sorted(Comparator.comparing(e -> e.name.length()))
    .collect(Collectors.toList());
System.out.println(sl);

					

The output of the above code is employee list in sorted by name length order:

[Nick, Steve, Nathaniel]
					

Comparator.thenComparing(...) is a default method of the Comparator interface introduced in Java 8. If we have two Comparator interface instances, and we want to do a sorting by composite condition (by first comparator and then by second comparator), we can use both comparators invoking thenComparing(...) on fist instance and passing in the second instance. Find the example below:


Stream<Employee> emps = Stream.of(
    new Employee("Nathaniel"), new Employee("Jane"),
    new Employee("Steve"), new Employee("Nick"),
    new Employee("Jack"));

Comparator<Employee> c1 = Comparator.comparing(e -> e.name.length());
Comparator<Employee> c2 = (e1, e2) -> e1.name.compareTo(e2.name);

List<Employee> sl = emps
    .sorted(c1.thenComparing(c2))
    .collect(Collectors.toList());
System.out.println(sl);

					

The output of the above code is employee list in sorted by name length order, and in case name lengths are equal, such employees are sorted by name alphabetical order:

[Jack, Jane, Nick, Steve, Nathaniel]
					

Professional hosting         Free 'Oracle Certified Expert Web Services Developer 6' Guide     Exam 1Z0-810: Upgrade to Java SE 8 Programmer Quiz