Java 8 – How to Chain Lambda Expressions for Complex Operations

Introduction

Java 8 introduced lambda expressions and the Stream API, providing developers with powerful tools for processing collections in a functional and declarative manner. Lambda expressions can be chained together to perform complex operations, making the code more concise, readable, and expressive. Chaining lambda expressions is particularly useful when you need to apply multiple transformations or filters to a collection.

In this blog post, we’ll explore how to chain lambda expressions to perform complex operations on collections in Java 8.

Table of Contents

  • Problem Statement
  • Solution Steps
  • Java Program
    • Chaining Lambda Expressions for Complex Operations
  • Advanced Considerations
  • Conclusion

Problem Statement

The task is to create a Java program that:

  • Applies multiple operations such as filtering, mapping, and sorting on a collection using chained lambda expressions.
  • Demonstrates the use of chaining lambda expressions to perform complex data processing tasks.

Example:

  • Input: A list of Product objects, each with attributes such as id, name, and price.
  • Output: A list of product names sorted alphabetically, where the price is greater than $500.

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. Chain Lambda Expressions: Use the Stream API to chain multiple lambda expressions for filtering, mapping, and sorting.
  4. Collect the Results: Use Collectors.toList() to collect the processed results into a new list.

Java Program

Chaining Lambda Expressions for Complex Operations

Below is an example that demonstrates how to chain lambda expressions to filter, map, and sort a list of Product objects.

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

/**
 * Java 8 - How to Chain Lambda Expressions for Complex Operations
 * 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 ChainLambdaExpressionsExample {

    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, "Smartwatch", 150.00));
        products.add(new Product(5, "Headphones", 100.00));

        // Step 2: Chain lambda expressions for filtering, mapping, and sorting
        List<String> productNames = products.stream()
            .filter(product -> product.getPrice() > 500)              // Filter products by price
            .map(Product::getName)                                    // Map to product names
            .sorted()                                                 // Sort product names alphabetically
            .collect(Collectors.toList());                            // Collect results to a list

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

Output

Laptop
Smartphone

Explanation

  • Product Class: The Product class defines the structure of a product with id, name, and price attributes.
  • Chaining Lambda Expressions: The Stream API is used to perform multiple operations on the list of products:
    • Filtering: filter(product -> product.getPrice() > 500) filters the products to include only those with a price greater than $500.
    • Mapping: map(Product::getName) maps the filtered products to their names.
    • Sorting: sorted() sorts the product names alphabetically.
  • Collecting Results: The Collectors.toList() method collects the processed product names into a new list, productNames.
  • Displaying the Results: The forEach(System.out::println) method is used to print each product name in the filtered and sorted list.

Advanced Considerations

  • Multiple Filters: You can chain multiple filter() methods to apply more complex filtering criteria. For example:

    products.stream()
        .filter(product -> product.getPrice() > 500)
        .filter(product -> product.getName().startsWith("S"))
        .map(Product::getName)
        .sorted()
        .collect(Collectors.toList());
    
  • Custom Sorting: If you need to sort by a custom attribute, you can provide a custom comparator to the sorted() method:

    products.stream()
        .filter(product -> product.getPrice() > 500)
        .sorted((p1, p2) -> p1.getName().compareTo(p2.getName()))
        .map(Product::getName)
        .collect(Collectors.toList());
    
  • Reducing: You can also chain a reduce() operation to combine elements into a single result after filtering and mapping.

Conclusion

This blog post demonstrated how to chain lambda expressions to perform complex operations on collections in Java 8. By leveraging the power of lambda expressions and the Stream API, you can efficiently filter, map, and sort collections in a concise and readable manner. Chaining lambda expressions is particularly useful when you need to apply multiple transformations or filters to a collection, making your code more expressive and maintainable. Whether you’re working with simple data types or complex objects, the Stream API and lambda expressions provide a powerful way to handle complex data processing tasks in Java.

Leave a Comment

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

Scroll to Top