![]() | |
|
Sorting a Stream
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 Stream.sorted()
is a stateful intermediate operation which
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.print(sl);
Output:
[Jack, Jane, John]
![]() | |
The
If the elements of this stream are not For ordered streams, the sort is stable. For unordered streams, no stability guarantees are made. |
We can use our own sorting logic by calling Stream.sorted(...)
intermediate operation
and passing a Comparator
interface as a parameter. The comparing(...)
and few other
useful static
and default
methods have been added to the
java.util.Comparator
interface in Java 8.0 to simplify these scenarios.
Here is an example how the Comparator.comparing(...)
method is used to provide a custom
sorting logic (e.g. when elements do not implement java.lang.Comparable
interface or when the same
elements need to be sorted by different algorithms).
public class Employee { public String name; public Employee(String n) { name = n; } public String getName() { return name; } @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.print(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.0. 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 first 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]
You can sort a stream in the reverse order by preparing a simple Comparator
instance for
the sort and then calling reversed()
method on it to get the reversed
version of that Comparator
:
Comparator<Employee> byNameLengthDesc = Comparator.comparing((Employee e) -> e.name.length()).reversed(); Stream<Employee> emps = Stream.of(new Employee("Nathaniel"), new Employee("Steve"), new Employee("Nick")); List<Employee> sl = emps .sorted(byNameLengthDesc) .collect(Collectors.toList()); System.out.print(sl);
[Nathaniel, Steve, Nick]
Sorting a List
The java.util.Collections.sort(...)
method sorts the specified List
into ascending order,
according to the natural ordering of its elements. All elements in the list must implement the
Comparable
interface. Furthermore, all elements in the list must be mutually comparable:
List<String> emps = new ArrayList<>(); emps.add("Nathaniel"); emps.add("Steve"); emps.add("Nick"); Collections.sort(emps); System.out.print(emps);
[Nathaniel, Nick, Steve]
![]() | |
If you initialize a list like this, it will fail at runtime, as the factory method creates immutable list object and sorting modifies exactly the same list object: List<String> emps = List.of("Nathaniel", "Steve","Nick");
|
If the objects in the list do not implement Comparable
, you should provide your custom
Comparator
:
List<Employee> emps = new ArrayList<>(); emps.add(new Employee("Nathaniel")); emps.add(new Employee("Steve")); emps.add(new Employee("Nick")); Comparator<Employee> c = (e1, e2) -> e1.name.compareTo(e2.name); Collections.sort(emps, c); System.out.print(emps);
[Nathaniel, Nick, Steve]
Or the same logic by using Comparator.comparing(...)
method:
Comparator<Employee> c = Comparator.comparing(e -> e.name);
Or using method reference syntax (assume Employee
has String getName()
method which
returns name
):
Comparator<Employee> c = Comparator.comparing(Employee::getName);
As of Java 8.0 the java.util.List
interface has default void sort(Comparator<? super E> c)
method which
can sort own elements:
List<Employee> emps = new ArrayList<>(); emps.add(new Employee("Nathaniel")); emps.add(new Employee("Steve")); emps.add(new Employee("Nick")); Comparator<Employee> c = Comparator.comparing(Employee::getName); emps.sort(c); System.out.print(emps);
[Nathaniel, Nick, Steve]
![]() ![]() ![]() |