In this post, we will see how to sort a list with Stream.sorted()
method.
Java 8 has introduced Stream.sort()
method to sort list of elements conveniently. It helps us to write short and concise functional style code rather than boilerplate code.
Table of Contents
sorted()
method.
sorted()
: Returns a stream having elements sorted by natural ordersorted(Comparator super T> comparator)
: Returns a stream having elements sorted by provided comparator
💡 Did you know?
If you sort list of Integers using
Stream.sorted()
method then Comparable interface, implemented byInteger
class, will define natural ordering of list of Integers .
Let’s understand how can we use Stream.sorted()
to sort list of elements.
Sort List of Integers
We can simply use sorted()
method to sort list of integers.
1 2 3 4 5 |
List<Integer> result = listOfIntegers.stream() .sorted() .collect(Collectors.toList()); |
Here, List of Integers is sorted by Comparable interface implemented by Integer class.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
public final class Integer extends Number implements Comparable<Integer> { .... /** * Compares two {@code Integer} objects numerically. * * @param anotherInteger the {@code Integer} to be compared. * @return the value {@code 0} if this {@code Integer} is * equal to the argument {@code Integer}; a value less than * {@code 0} if this {@code Integer} is numerically less * than the argument {@code Integer}; and a value greater * than {@code 0} if this {@code Integer} is numerically * greater than the argument {@code Integer} (signed * comparison). * @since 1.2 */ public int compareTo(Integer anotherInteger) { return compare(this.value, anotherInteger.value); } /** * Compares two {@code int} values numerically. * The value returned is identical to what would be returned by: * * Integer.valueOf(x).compareTo(Integer.valueOf(y)) * * * @param x the first {@code int} to compare * @param y the second {@code int} to compare * @return the value {@code 0} if {@code x == y}; * a value less than {@code 0} if {@code x < y}; and * a value greater than {@code 0} if {@code x > y} * @since 1.7 */ public static int compare(int x, int y) { return (x < y) ? -1 : ((x == y) ? 0 : 1); } |
As you can see, Integers are compared on this basis of (x < y) ? -1 : ((x == y) ? 0 : 1)
logic.
You can pass Comparator.reverseOrder()
to sorted method to reverse sort list of Integers.
1 2 3 4 5 |
List<Integer> reverseOrder = listOfIntegers.stream() .sorted(Comparator.reverseOrder()) .collect(Collectors.toList()); |
Comparator.reverseOrder()
is static method and provides a comparator that imposes reverse of natural ordering.
Let’s see complete example to sort list of integers.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
package org.arpit.java2blog; import java.util.Arrays; import java.util.Comparator; import java.util.List; import java.util.stream.Collectors; public class SortListOfIntegers { public static void main(String[] args) { List<Integer> listOfIntegers = Arrays.asList(new Integer[] {40,34,21,37,20}); List<Integer> result = listOfIntegers.stream() .sorted() .collect(Collectors.toList()); System.out.println(result); List<Integer> reverseOrder = listOfIntegers.stream() .sorted(Comparator.reverseOrder()) .collect(Collectors.toList()); System.out.println(reverseOrder); } } |
Output:
Sort List of Strings
We can simply use sorted()
method to sort list of Strings.
1 2 3 4 5 |
List<String> result = listOfStrings.stream() .sorted() .collect(Collectors.toList()); |
Here, List of Strings is sorted by Comparable interface implemented by String class.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
public final class String implements java.io.Serializable, Comparable<String>, CharSequence { .... /** * Compares two strings lexicographically. * * @param anotherString the {@code String} to be compared. * @return the value {@code 0} if the argument string is equal to * this string; a value less than {@code 0} if this string * is lexicographically less than the string argument; and a * value greater than {@code 0} if this string is * lexicographically greater than the string argument. */ public int compareTo(String anotherString) { int len1 = value.length; int len2 = anotherString.value.length; int lim = Math.min(len1, len2); char v1[] = value; char v2[] = anotherString.value; int k = 0; while (k < lim) { char c1 = v1[k]; char c2 = v2[k]; if (c1 != c2) { return c1 - c2; } k++; } return len1 - len2; } |
As you can see, Integers are compared on this basis of (x < y) ? -1 : ((x == y) ? 0 : 1)
logic.
You can pass Comparator.reverseOrder()
to sorted method to reverse sort list of Integers.
1 2 3 4 5 |
List<String> reverseOrder = listOfStrings.stream() .sorted(Comparator.reverseOrder()) .collect(Collectors.toList()); |
Comparator.reverseOrder() is static method and provides a comparator that imposes reverse of natural ordering.
Let’s see complete example to sort list of integers.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
package org.arpit.java2blog; import java.util.Arrays; import java.util.Comparator; import java.util.List; import java.util.stream.Collectors; public class SortListOfStrings { public static void main(String[] args) { List<String> listOfLanguages = Arrays.asList(new String[] { "Python", "C++", "Java", "PHP" }); List<String> sortedListOfLanguages = listOfLanguages.stream() .sorted() .collect(Collectors.toList()); System.out.println(sortedListOfLanguages); List<String> sortedListOfLanguagesRev = listOfLanguages.stream() .sorted(Comparator.reverseOrder()) .collect(Collectors.toList()); System.out.println(sortedListOfLanguagesRev); } } |
Output:
Sort List of custom objects
Sort list of Students by natural order
Create a class named Student.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
package org.arpit.java2blog; public class Student{ String name; int age; public Student(String name, int age) { super(); this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Student [name=" + name + ", age=" + age + "]"; } } |
Let’s use Stream’s sorted() to sort the list of Students now.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
package org.arpit.java2blog; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; public class SortListOfStudents { public static void main(String[] args) { List<Student> studentsList = getListOfStudents(); List<Student> sortedStudentsList= studentsList.stream() .sorted() .collect(Collectors.toList()); System.out.println(sortedStudentsList); } public static List<Student> getListOfStudents() { List<Student> studentList=new ArrayList<>(); Student s1=new Student("Peter",21); Student s2=new Student("Harshal",18); Student s3=new Student("Andy",17); Student s4=new Student("Mary",20); Student s5=new Student("Peter",19); studentList.add(s1); studentList.add(s2); studentList.add(s3); studentList.add(s4); studentList.add(s5); return studentList; } } |
Let’s run above program.
at java.util.Comparators$NaturalOrderComparator.compare(Comparators.java:47)
at java.util.TimSort.countRunAndMakeAscending(TimSort.java:355)
at java.util.TimSort.sort(TimSort.java:220)
at java.util.Arrays.sort(Arrays.java:1512)
at java.util.stream.SortedOps$SizedRefSortingSink.end(SortedOps.java:353)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:483)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472)
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:566)
at org.arpit.java2blog.SortListOfStudents.main(SortListOfStudents.java:14)
Did you know why we got exception here?
We got the ClassCastException
exception because we did not implement Comparable
interface in Student
class.
Let’s implement Comparable interface in Student
class.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
package org.arpit.java2blog; public class Student implements Comparable<Student>{ String name; int age; public Student(String name, int age) { super(); this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Student [name=" + name + ", age=" + age + "]"; } @Override public int compareTo(Student o) { return this.getName().compareTo(o.getName()); } } |
Run SortListOfStudents
again, and you will get below output.
As you can see, list of Students is sorted by student name.
Sort list of Students by reverse natural order
Sort list of Students by name in descending order.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
package org.arpit.java2blog; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; public class SortListOfStudents { public static void main(String[] args) { List<Student> studentsList = getListOfStudents(); List<Student> sortedListOfStudent2 = listOfStudents.stream() .sorted(Comparator.reverseOrder()) .collect(Collectors.toList()); System.out.println(sortedStudentsList); } public static List<Student> getListOfStudents() { List<Student> studentList=new ArrayList<>(); Student s1=new Student("Peter",21); Student s2=new Student("Harshal",18); Student s3=new Student("Andy",17); Student s4=new Student("Mary",20); Student s5=new Student("Peter",19); studentList.add(s1); studentList.add(s2); studentList.add(s3); studentList.add(s4); studentList.add(s5); return studentList; } } |
Output:
Sort list of Students by age using comparator
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
package org.arpit.java2blog; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; public class SortListOfStudents { public static void main(String[] args) { List<Student> studentsList = getListOfStudents(); List<Student> studentsListByAge = studentsList.stream() .sorted((s1,s2) -> s1.getAge()-s2.getAge()) .collect(Collectors.toList()); System.out.println(studentsListByAge); } public static List<Student> getListOfStudents() { List<Student> studentList=new ArrayList<>(); Student s1=new Student("Peter",21); Student s2=new Student("Harshal",18); Student s3=new Student("Andy",17); Student s4=new Student("Mary",20); Student s5=new Student("Peter",19); studentList.add(s1); studentList.add(s2); studentList.add(s3); studentList.add(s4); studentList.add(s5); return studentList; } } |
Output:
You can also use Comparator.comparing(Function<? super T, ? extends U> keyExtractor)
to sort it on the basis of age.
Comparator.comparing()
accepts a function that maps a sort key from a type, and returns a Comparator that compares by that sort key.
Let’s say you want to sort list of Students on the basis of age. You can extracts sort key age from Student object and Comparator.comparing()
will return a comparator which will sort by that sort key.
1 2 3 4 5 6 |
Function<Student,Integer> fun = (s) -> s.getAge(); List<Student> studentsListByAge = studentsList.stream() .sorted(Comparator.comparing(fun)) .collect(Collectors.toList()); |
Here Comparator.comparing()
returns a new Comparator to sort based on age.
We can also use method reference here as we are just calling s.getAge() in the functional interface.
1 2 3 4 5 6 |
Function<Student,Integer> fun = Student::getAge List<Student> studentsListByAge = studentsList.stream() .sorted(Comparator.comparing(fun)) .collect(Collectors.toList()); |
Let’s say you want to sort list of Students on the basis of age in descending order. You can pass another comparator to Comparator.comparing()
to make custom sorting based on sort key.
1 2 3 4 5 |
List<Student> sortedListOfStudent5 = listOfStudents.stream() .sorted(Comparator.comparing(Student::getAge,(age1,age2) -> age2 - age1)) .collect(Collectors.toList()); |
Here,
Comparator.comparing() has two arguments.
Student::getAge
to define sort key.
(age1,age2) -> age2 - age1)
to define custom sorting on the basis of sort key.
Here is the complete example.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
package org.arpit.java2blog; import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.function.Function; import java.util.stream.Collectors; public class SortListOfStudents { public static void main(String[] args) { List<Student> sList = getListOfStudents(); Function<Student,Integer> fun = (s) -> s.getAge(); List<Student> sListByAge = sList.stream() .sorted(Comparator.comparing(fun)) .collect(Collectors.toList()); System.out.println("Sorted list by age ascending: "+sListByAge); List<Student> sListByAgeRev = sList.stream() .sorted(Comparator.comparing(Student::getAge ,(age1,age2) -> age2 - age1)) .collect(Collectors.toList()); System.out.println("Sorted list by age descending: "+sListByAgeRev); } public static List<Student> getListOfStudents() { List<Student> studentList=new ArrayList<>(); Student s1=new Student("Peter",21); Student s2=new Student("Harshal",18); Student s3=new Student("Andy",17); Student s4=new Student("Mary",20); Student s5=new Student("Peter",19); studentList.add(s1); studentList.add(s2); studentList.add(s3); studentList.add(s4); studentList.add(s5); return studentList; } } |
Output:
Sort list of Students by name and age
Let’s say you want to list of students by name and if name is same, then you need to sort by age.
You can use Comparator.thenComparing() with Comparator.comparing() to achieve the same.
Let’s see with the help of example.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
package org.arpit.java2blog; import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.stream.Collectors; public class SortListOfStudents { public static void main(String[] args) { List<Student> sList = getListOfStudents(); List<Student> sListByNameAge = sList.stream() .sorted(Comparator.comparing(Student::getName) .thenComparing(Student::getAge)) .collect(Collectors.toList()); System.out.println(sListByNameAge); } public static List<Student> getListOfStudents() { List<Student> studentList=new ArrayList<>(); Student s1=new Student("Peter",21); Student s2=new Student("Harshal",18); Student s3=new Student("Andy",17); Student s4=new Student("Mary",20); Student s5=new Student("Peter",19); studentList.add(s1); studentList.add(s2); studentList.add(s3); studentList.add(s4); studentList.add(s5); return studentList; } } |
Output:
As you can see, there are two students named Peter
in the list then, sorted by age.
Excercise
Given a list of Employee objects, you need to sort them of Employee’s name in descending order and return a sorted list of Employee(List
)
Here is the definition of Employee class.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
package org.arpit.java2blog; public class Employee { String name; public Employee(String name) { super(); this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Employee [name=" + name + "]"; } } |
That’s all about Java Stream sorted example.