Introduction
Sorting a list of objects by multiple fields is a common requirement in many applications, especially when dealing with complex data. For example, you might need to sort a list of employees first by department, and then by age within each department. Java 8 introduced the Stream API, which simplifies the sorting process and allows for easy chaining of multiple sorting conditions. In this guide, we’ll explore how to sort a list of objects by multiple fields using Java 8 Streams, covering various use cases with custom objects.
Table of Contents
- Problem Statement
- Solution Steps
- Java Program
- Sorting a List of Custom Objects by Multiple Fields
- Sorting by Multiple Fields with Different Orders
 
- Advanced Considerations
- Conclusion
Problem Statement
The task is to create a Java program that:
- Accepts a list of custom objects.
- Sorts the list by multiple fields.
- Outputs the sorted list.
Example 1:
- Input: List of Studentobjects, sort first byageand then byname.
- Output: The list of students sorted by age, and within the same age, sorted byname.
Example 2:
- Input: List of Employeeobjects, sort first bydepartment, then bysalaryin descending order.
- Output: The list of employees sorted by department, and within the same department, sorted bysalaryin descending order.
Solution Steps
- Input List: Start with a list of custom objects that can either be hardcoded or provided by the user.
- Sort the List Using Streams: Use the sorted()method with a custom comparator to sort the list by multiple fields.
- Display the Result: Print the sorted list.
Java Program
Sorting a List of Custom Objects by Multiple Fields
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
/**
 * Java 8 - Sort a List of Objects by Multiple Fields
 * Author: https://www.rameshfadatare.com/
 */
public class SortByMultipleFields {
    public static void main(String[] args) {
        // Step 1: Take input list of custom objects
        List<Student> students = Arrays.asList(
                new Student("Raj", 25),
                new Student("Anita", 30),
                new Student("Vikram", 22),
                new Student("Anita", 22)
        );
        // Step 2: Sort the list by age and then by name
        List<Student> sortedStudents = students.stream()
                                               .sorted(Comparator.comparing(Student::getAge)
                                                                 .thenComparing(Student::getName))
                                               .toList();
        // Step 3: Display the result
        sortedStudents.forEach(student -> 
            System.out.println(student.getName() + ": " + student.getAge())
        );
    }
}
// Custom class Student
class Student {
    private String name;
    private int age;
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public int getAge() {
        return age;
    }
}
Output
Anita: 22
Vikram: 22
Raj: 25
Anita: 30
Explanation
- The stream()method is used to create a stream from the list ofStudentobjects.
- The sorted()method is applied with a custom comparator that first sorts byageusingComparator.comparing(Student::getAge).
- The thenComparing(Student::getName)method is chained to the comparator to sort bynamewithin the same age group.
- The result is a sorted list of Studentobjects, which is printed out in the order defined by the sort criteria.
Sorting by Multiple Fields with Different Orders
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
/**
 * Java 8 - Sort a List of Objects by Multiple Fields with Different Orders
 * Author: https://www.rameshfadatare.com/
 */
public class SortByMultipleFieldsDifferentOrders {
    public static void main(String[] args) {
        // Step 1: Take input list of custom objects
        List<Employee> employees = Arrays.asList(
                new Employee("Raj", "IT", 60000),
                new Employee("Anita", "HR", 75000),
                new Employee("Vikram", "IT", 55000),
                new Employee("Anita", "IT", 62000)
        );
        // Step 2: Sort the list by department, then by salary (descending)
        List<Employee> sortedEmployees = employees.stream()
                                                  .sorted(Comparator.comparing(Employee::getDepartment)
                                                                    .thenComparing(Employee::getSalary).reversed())
                                                  .toList();
        // Step 3: Display the result
        sortedEmployees.forEach(employee -> 
            System.out.println(employee.getName() + ": " + employee.getDepartment() + ", Salary: " + employee.getSalary())
        );
    }
}
// Custom class Employee
class Employee {
    private String name;
    private String department;
    private int salary;
    public Employee(String name, String department, int salary) {
        this.name = name;
        this.department = department;
        this.salary = salary;
    }
    public String getName() {
        return name;
    }
    public String getDepartment() {
        return department;
    }
    public int getSalary() {
        return salary;
    }
}
Output
Vikram: IT, Salary: 55000
Anita: IT, Salary: 62000
Raj: IT, Salary: 60000
Anita: HR, Salary: 75000
Explanation
- The list of Employeeobjects is sorted first bydepartmentusingComparator.comparing(Employee::getDepartment).
- The thenComparing(Employee::getSalary).reversed()method is chained to sort bysalaryin descending order within each department.
- The result is a sorted list of Employeeobjects, which is printed out in the order defined by the sort criteria.
Advanced Considerations
- 
Null Handling: When sorting by fields that might be null, you can useComparator.nullsFirst()orComparator.nullsLast()to handlenullvalues gracefully. For example:Comparator.comparing(Employee::getDepartment, Comparator.nullsLast(Comparator.naturalOrder()))
- 
Multiple Field Sorting in Parallel Streams: Sorting with parallel streams can lead to non-deterministic results if the sort order depends on encounter order. Ensure that the sorting logic accounts for this when using parallel streams. 
- 
Performance Considerations: Sorting by multiple fields using Streams is efficient for typical list sizes. However, for very large lists, consider the performance implications and test the sorting operation with your specific dataset. 
Conclusion
This guide provides methods for sorting a list of objects by multiple fields using Java 8 Streams, covering both simple and complex sorting scenarios. Java 8 Streams offer a powerful and flexible way to sort lists, making your code more readable and maintainable. Depending on your specific use case, you can easily apply the techniques demonstrated in this guide to achieve the desired sorting order.