Sitelet https://java2blog.com/java-stream-sorted/

Java Stream sorted example

Java Stream Sorted

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.
[toc]
java.util.Stream has two overloaded versions of sorted() method.

  1. sorted(): Returns a stream having elements sorted by natural order
  2. sorted(Comparator 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 by Integer 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.

List result = listOfIntegers.stream()
                                         .sorted()
                                         .collect(Collectors.toList());

Here, List of Integers is sorted by Comparable interface implemented by Integer class.

public final class Integer extends Number implements Comparable {
....
/**
     * 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.

List 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.

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 listOfIntegers = Arrays.asList(new Integer[] {40,34,21,37,20});

        List result = listOfIntegers.stream()
                                                .sorted()
                                                .collect(Collectors.toList());
        System.out.println(result);

        List reverseOrder = listOfIntegers.stream()
                                                     .sorted(Comparator.reverseOrder())
                                                     .collect(Collectors.toList());
        System.out.println(reverseOrder);
    }

}

Output:

[20, 21, 34, 37, 40]
[40, 37, 34, 21, 20]

Sort List of Strings

We can simply use sorted() method to sort list of Strings.

List result = listOfStrings.stream()
                                         .sorted()
                                         .collect(Collectors.toList());

Here, List of Strings is sorted by Comparable interface implemented by String class.

public final class String
    implements java.io.Serializable, Comparable, 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.

List 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.

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 listOfLanguages = Arrays.asList(new String[] { "Python", "C++", "Java", "PHP" });

        List sortedListOfLanguages = listOfLanguages.stream()
                                                              .sorted()
                                                              .collect(Collectors.toList());
        System.out.println(sortedListOfLanguages);

        List sortedListOfLanguagesRev = listOfLanguages.stream()
                                                                 .sorted(Comparator.reverseOrder())
                                                                 .collect(Collectors.toList());
        System.out.println(sortedListOfLanguagesRev);  
    }

}

Output:

[C++, Java, PHP, Python]
[Python, PHP, Java, C++]

Sort List of custom objects

Sort list of Students by natural order

Create a class named Student.java

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.

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 studentsList = getListOfStudents();

        List sortedStudentsList= studentsList.stream()
                                                          .sorted()
                                                          .collect(Collectors.toList());
        System.out.println(sortedStudentsList);
    }

    public static List getListOfStudents()
    {
        List 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.

Exception in thread "main" java.lang.ClassCastException: org.arpit.java2blog.Student cannot be cast to java.lang.Comparable
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.

package org.arpit.java2blog;

public class Student implements Comparable{

    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.

[Student [name=Andy, age=17], Student [name=Harshal, age=18], Student [name=Mary, age=20], Student [name=Peter, age=21], Student [name=Peter, age=19]]

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.

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 studentsList = getListOfStudents();

        List sortedListOfStudent2 = listOfStudents.stream()
                                                           .sorted(Comparator.reverseOrder())
                                                           .collect(Collectors.toList());
        System.out.println(sortedStudentsList);
    }

    public static List getListOfStudents()
    {
        List 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:

[Student [name=Peter, age=21], Student [name=Peter, age=19], Student [name=Mary, age=20], Student [name=Harshal, age=18], Student [name=Andy, age=17]]

Sort list of Students by age using comparator

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 studentsList = getListOfStudents();

        List studentsListByAge = studentsList.stream()
                                                         .sorted((s1,s2) -> s1.getAge()-s2.getAge())
                                                         .collect(Collectors.toList());
        System.out.println(studentsListByAge);
    }

    public static List getListOfStudents()
    {
        List 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:

[Student [name=Andy, age=17], Student [name=Harshal, age=18], Student [name=Peter, age=19], Student [name=Mary, age=20], Student [name=Peter, age=21]]

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.

Function fun = (s) -> s.getAge();
    List 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.

Function fun = Student::getAge
    List 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.

List 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.

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 sList = getListOfStudents();

        Function fun = (s) -> s.getAge();
        List sListByAge = sList.stream()
                                         .sorted(Comparator.comparing(fun))
                                         .collect(Collectors.toList());
        System.out.println("Sorted list by age ascending: "+sListByAge);

        List 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 getListOfStudents()
    {
        List 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:

Sorted list by age ascending: [Student [name=Andy, age=17], Student [name=Harshal, age=18], Student [name=Peter, age=19], Student [name=Mary, age=20], Student [name=Peter, age=21]]
Sorted list by age descending: [Student [name=Peter, age=21], Student [name=Mary, age=20], Student [name=Peter, age=19], Student [name=Harshal, age=18], Student [name=Andy, age=17]]

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.

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 sList = getListOfStudents();

        List sListByNameAge = sList.stream()
                                           .sorted(Comparator.comparing(Student::getName)
                                                             .thenComparing(Student::getAge))
                                           .collect(Collectors.toList());

        System.out.println(sListByNameAge);
    }

    public static List getListOfStudents()
    {
        List 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:

[Student [name=Andy, age=17], Student [name=Harshal, age=18], Student [name=Mary, age=20], Student [name=Peter, age=19], Student [name=Peter, age=21]]

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.

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 + "]";
    }
}

[showhide type="question1" more_text="Show Answer" less_text="Hide Answers"]
We can use pass comparator to sorted() method or Comparator.comparing() to sort list of employee by name in descending order.

package org.arpit.java2blog;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

public class SortListOfEmployees {

	public static void main(String[] args) {
		List eList=getListOfEmployees();
		
		List eListDesc1 = eList.stream()
				                        .sorted((e1,e2) -> e2.getName().compareTo(e1.getName()))
		                                .collect(Collectors.toList());
		
		System.out.println(eListDesc1);
		
		List eListDesc2 = eList.stream().sorted(Comparator.comparing(Employee::getName
																			,(s1,s2)->s2.compareTo(s1)))
	                                              .collect(Collectors.toList());
		System.out.println(eListDesc2);
		
	}
	private static List getListOfEmployees() {
		
		List listOfEmployees=new ArrayList<>();
		
		Employee e1=new Employee("Shahid");
		Employee e2=new Employee("Anchit");
		Employee e3=new Employee("Chetan");
		Employee e4=new Employee("Vikrant");
		
		listOfEmployees.add(e1);
		listOfEmployees.add(e2);
		listOfEmployees.add(e3);
		listOfEmployees.add(e4);
		
		return listOfEmployees;
	}

}

Output:

[Employee [name=Vikrant], Employee [name=Shahid], Employee [name=Chetan], Employee [name=Anchit]]
[Employee [name=Vikrant], Employee [name=Shahid], Employee [name=Chetan], Employee [name=Anchit]]

[/showhide]

That's all about Java Stream sorted example.

[social_share share_on="facebook,twitter,linkedin,whatsapp"][post_navigator in_same_term="true"]

Leave a Reply

Your email address will not be published. Required fields are marked *

Subscribe to our newletter

Get quality tutorials to your inbox. Subscribe now.