Java 8 – How to Use Lambda Expressions to Sort by Multiple Fields

Introduction

Java 8 introduced lambda expressions and the Stream API, which brought new ways to process collections in a more concise and functional manner. Sorting a collection by multiple fields is a common requirement in many applications, such as sorting a list of objects first by one attribute (e.g., name) and then by another (e.g., price). Before Java 8, achieving this required writing complex comparator logic. With lambda expressions and the Comparator class enhancements, sorting by multiple fields has become much simpler.

In this blog post, we’ll explore how to use lambda expressions to sort a list of objects by multiple fields in Java 8.

Table of Contents

  • Problem Statement
  • Solution Steps
  • Java Program
    • Sorting by Multiple Fields Using Lambda Expressions
  • Advanced Considerations
  • Conclusion

Problem Statement

The task is to create a Java program that:

  • Sorts a list of custom objects by multiple fields using lambda expressions.
  • Demonstrates how to achieve primary and secondary sorting using the Comparator class in Java 8.

Example:

  • Input: A list of Product objects, each with attributes such as name and price.
  • Output: The list sorted first by name alphabetically and then by price in ascending order.

Solution Steps

  1. Create a Product Class: Define a Product class with attributes such as id, name, and price.
  2. Create a List of Product Objects: Define a list of Product objects.
  3. Use the Comparator Class: Utilize the Comparator.comparing() method and lambda expressions to sort by multiple fields.
  4. Chain Comparators: Use thenComparing() to chain multiple comparators for sorting.

Java Program

Sorting by Multiple Fields Using Lambda Expressions

Below is an example that demonstrates how to sort a list of Product objects first by name and then by price.

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

/**
 * Java 8 - How to Use Lambda Expressions to Sort by Multiple Fields
 * Author: https://www.rameshfadatare.com/
 */
class Product {
    private int id;
    private String name;
    private double price;

    public Product(int id, String name, double price) {
        this.id = id;
        this.name = name;
        this.price = price;
    }

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public double getPrice() {
        return price;
    }

    @Override
    public String toString() {
        return "Product{id=" + id + ", name='" + name + "', price=" + price + "}";
    }
}

public class SortByMultipleFieldsExample {

    public static void main(String[] args) {
        // Step 1: Create a list of Product objects
        List<Product> products = new ArrayList<>();
        products.add(new Product(1, "Laptop", 1200.00));
        products.add(new Product(2, "Smartphone", 800.00));
        products.add(new Product(3, "Tablet", 300.00));
        products.add(new Product(4, "Smartphone", 1200.00));
        products.add(new Product(5, "Smartwatch", 150.00));
        products.add(new Product(6, "Headphones", 150.00));

        // Step 2: Sort the list by name and then by price using lambda expressions
        products.sort(Comparator.comparing(Product::getName)
            .thenComparing(Product::getPrice));

        // Step 3: Display the sorted list
        products.forEach(System.out::println);
    }
}

Output

Product{id=6, name='Headphones', price=150.0}
Product{id=1, name='Laptop', price=1200.0}
Product{id=5, name='Smartwatch', price=150.0}
Product{id=2, name='Smartphone', price=800.0}
Product{id=4, name='Smartphone', price=1200.0}
Product{id=3, name='Tablet', price=300.0}

Explanation

  • Product Class: The Product class defines the structure of a product with id, name, and price attributes.
  • Sorting by Multiple Fields: The Comparator.comparing(Product::getName) creates a comparator that sorts the products by name. The thenComparing(Product::getPrice) chains a second comparator that sorts by price for products with the same name.
  • Sorting Order: By default, Comparator.comparing() sorts in ascending order. If you want to sort in descending order, you can use Comparator.comparing(Product::getName).reversed() or Comparator.comparing(Product::getPrice).reversed().

Advanced Considerations

  • Sorting by Multiple Fields with Custom Logic: You can use custom comparator logic in thenComparing() if your sorting criteria are more complex:

    products.sort(Comparator.comparing(Product::getName)
        .thenComparing((p1, p2) -> Double.compare(p2.getPrice(), p1.getPrice()))); // Descending price
    
  • Null Handling: If your list might contain null values, consider using Comparator.nullsFirst() or Comparator.nullsLast():

    products.sort(Comparator.comparing(Product::getName, Comparator.nullsFirst(String::compareTo))
        .thenComparing(Product::getPrice));
    
  • Combining Multiple Comparators: You can continue chaining as many thenComparing() methods as necessary to sort by multiple fields.

Conclusion

This blog post demonstrated how to use lambda expressions to sort a list of objects by multiple fields in Java 8. By leveraging the Comparator.comparing() and thenComparing() methods, you can easily create complex sorting logic that is both concise and readable. Whether you’re sorting by two fields or more, these tools provide a powerful way to manage complex data sorting requirements in your Java applications.

Leave a Comment

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

Scroll to Top