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
Productobjects, each with attributes such asid,name, andprice. - Output: A list of product names sorted alphabetically, where the price is greater than $500.
Solution Steps
- Create a
ProductClass: Define aProductclass with attributes such asid,name, andprice. - Create a List of
ProductObjects: Define a list ofProductobjects. - Chain Lambda Expressions: Use the Stream API to chain multiple lambda expressions for filtering, mapping, and sorting.
- 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
Productclass defines the structure of a product withid,name, andpriceattributes. - 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.
- Filtering:
- 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.