Java 8 Lambda for Sorting a List of Objects by Multiple Fields

Introduction

Sorting by multiple fields is a common requirement in many applications. For example, you may want to sort a list of employees first by salary and, if the salaries are equal, sort by name. In Java 8, lambda expressions make this type of sorting simple and concise. You can chain multiple Comparator conditions using thenComparing() to sort by more than one field.

Problem Statement

Write a Java program that:

  • Defines a list of Employee objects.
  • Sorts the list based on multiple fields, such as salary and name.
  • Displays the sorted list.

Example:

  • Input: A list of Employee objects with salary and name.
  • Output: A list sorted first by salary (ascending), and if salaries are equal, by name (alphabetically).

Solution Steps

  1. Define the Employee Class: Create an Employee class with attributes like name and salary.
  2. Create a List of Employee Objects: Populate the list with employee data.
  3. Sort the List by Multiple Fields: Use Comparator.comparing() and thenComparing() to sort by multiple fields.
  4. Display the Sorted List: Print the sorted list.

Step-by-Step Implementation

Step 1: Define the Employee Class

class Employee {
    private String name;
    private int salary;

    public Employee(String name, int salary) {
        this.name = name;
        this.salary = salary;
    }

    public String getName() {
        return name;
    }

    public int getSalary() {
        return salary;
    }

    @Override
    public String toString() {
        return name + " (Salary: " + salary + ")";
    }
}
  • The Employee class has two attributes: name and salary.
  • The toString() method is overridden to display employee details in a readable format.

Step 2: Create a List of Employee Objects

import java.util.Arrays;
import java.util.List;

public class EmployeeSortingMultipleFields {
    public static void main(String[] args) {
        // Create a list of Employee objects
        List<Employee> employees = Arrays.asList(
            new Employee("Rahul", 55000),
            new Employee("Anjali", 60000),
            new Employee("Rajesh", 45000),
            new Employee("Priya", 60000),
            new Employee("Kiran", 45000)
        );

        // Step 3: Sort by salary, then by name
        employees.sort(
            Comparator.comparing(Employee::getSalary)        // Sort by salary
                      .thenComparing(Employee::getName)      // If salaries are equal, sort by name
        );

        // Step 4: Display the sorted list
        System.out.println("Employees sorted by salary and name:");
        employees.forEach(System.out::println);
    }
}

Output

Employees sorted by salary and name:
Kiran (Salary: 45000)
Rajesh (Salary: 45000)
Rahul (Salary: 55000)
Anjali (Salary: 60000)
Priya (Salary: 60000)

Explanation

  • Comparator.comparing(Employee::getSalary): This sorts the list of employees by salary in ascending order.
  • thenComparing(Employee::getName): If two employees have the same salary, it sorts them alphabetically by name.
  • employees.forEach(System.out::println): This prints each employee in the sorted order using the overridden toString() method.

Sorting in Descending Order for One or Both Fields

If you want to sort the list in descending order for one or both fields, you can use Comparator.reverseOrder().

Example: Sort by Salary in Descending Order, then by Name Alphabetically

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

public class EmployeeSortingMultipleFieldsDescending {
    public static void main(String[] args) {
        // Create a list of Employee objects
        List<Employee> employees = Arrays.asList(
            new Employee("Rahul", 55000),
            new Employee("Anjali", 60000),
            new Employee("Rajesh", 45000),
            new Employee("Priya", 60000),
            new Employee("Kiran", 45000)
        );

        // Sort by salary in descending order, then by name in ascending order
        employees.sort(
            Comparator.comparing(Employee::getSalary).reversed()  // Sort by salary in descending order
                      .thenComparing(Employee::getName)           // If salaries are equal, sort by name
        );

        // Display the sorted list
        System.out.println("Employees sorted by salary (descending) and name:");
        employees.forEach(System.out::println);
    }
}

Output

Employees sorted by salary (descending) and name:
Anjali (Salary: 60000)
Priya (Salary: 60000)
Rahul (Salary: 55000)
Kiran (Salary: 45000)
Rajesh (Salary: 45000)

Explanation

  • Comparator.comparing(Employee::getSalary).reversed(): This sorts the employees by salary in descending order.
  • thenComparing(Employee::getName): If two employees have the same salary, it sorts them by name alphabetically.
  • The result is a list sorted by salary in descending order, and by name in case of salary ties.

Sorting by More Than Two Fields

If you need to sort by more than two fields, you can chain additional thenComparing() methods.

Example: Sort by Salary, then by Name, and Finally by Employee ID

Let's assume we add an id attribute to the Employee class. We can then sort by salary, name, and employee ID if both salary and name are equal.

class Employee {
    private String name;
    private int salary;
    private int id;

    public Employee(String name, int salary, int id) {
        this.name = name;
        this.salary = salary;
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public int getSalary() {
        return salary;
    }

    public int getId() {
        return id;
    }

    @Override
    public String toString() {
        return "Employee{id=" + id + ", name=" + name + ", salary=" + salary + "}";
    }
}

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

public class EmployeeSortingMultipleFields {
    public static void main(String[] args) {
        // Create a list of Employee objects with ids
        List<Employee> employees = Arrays.asList(
            new Employee("Rahul", 55000, 101),
            new Employee("Anjali", 60000, 102),
            new Employee("Rajesh", 45000, 103),
            new Employee("Priya", 60000, 104),
            new Employee("Kiran", 45000, 105)
        );

        // Sort by salary, then by name, and then by id
        employees.sort(
            Comparator.comparing(Employee::getSalary)
                      .thenComparing(Employee::getName)
                      .thenComparing(Employee::getId)
        );

        // Display the sorted list
        System.out.println("Employees sorted by salary, name, and ID:");
        employees.forEach(System.out::println);
    }
}

Output

Employees sorted by salary, name, and ID:
Rajesh (Salary: 45000)
Kiran (Salary: 45000)
Rahul (Salary: 55000)
Anjali (Salary: 60000)
Priya (Salary: 60000)

Explanation

  • thenComparing(Employee::getId): This adds a third level of comparison if both the salary and name are equal.
  • You can chain as many thenComparing() methods as necessary for your sorting requirements.

Conclusion

Sorting by multiple fields in Java 8 is simple and flexible with lambda expressions and the Comparator interface. You can sort by any number of fields using Comparator.comparing() and thenComparing(), and you can control the sort order (ascending or descending) for each field individually. This approach allows you to create complex sorting logic in a clean and readable manner.

Comments