The Java 8 Stream API is one of the most powerful features introduced in Java 8. It provides a functional and declarative way to process collections efficiently. Unlike traditional loops, streams enable lazy evaluation, parallel execution, and concise code.
In this guide, we will explore real-world use cases of the Java Stream API with practical examples.
🔹 What is Java Stream API?
A Stream is a sequence of elements supporting aggregate operations like filtering, mapping, and reducing. Streams do not modify the original collection; instead, they create a new transformed version.
✔ Supports functional programming (using lambdas)
✔ Lazy evaluation (processes elements only when needed)
✔ Parallel execution (parallelStream()
)
✔ Works with Collections, Arrays, Files, and I/O
🔹 Real-World Use Cases of Java Streams
1️⃣ Filtering and Sorting a List (E-Commerce Example)
In an e-commerce application, we may need to filter products by price and sort them by name.
Example: Filter Products Cheaper Than ₹500 and Sort by Name
import java.util.*;
import java.util.stream.Collectors;
class Product {
private String name;
private double price;
public Product(String name, double price) {
this.name = name;
this.price = price;
}
public String getName() { return name; }
public double getPrice() { return price; }
@Override
public String toString() {
return name + " - ₹" + price;
}
}
public class StreamExample {
public static void main(String[] args) {
List<Product> products = Arrays.asList(
new Product("Laptop", 70000),
new Product("Mouse", 499),
new Product("Keyboard", 999),
new Product("Monitor", 5000)
);
// Filter products below ₹500 and sort by name
List<Product> filteredProducts = products.stream()
.filter(p -> p.getPrice() < 500)
.sorted(Comparator.comparing(Product::getName))
.collect(Collectors.toList());
filteredProducts.forEach(System.out::println);
}
}
📌 Key Takeaway:
✔ Use filter()
for extracting data and sorted()
for sorting based on conditions.
2️⃣ Converting List of Objects to a List of Strings
Many applications require extracting specific fields from objects and storing them separately.
Example: Extracting Product Names from a List
List<String> productNames = products.stream()
.map(Product::getName) // Extract names
.collect(Collectors.toList());
System.out.println(productNames); // Output: [Laptop, Mouse, Keyboard, Monitor]
📌 Key Takeaway:
✔ Use map()
to extract specific fields from objects.
3️⃣ Aggregating Data (Summing Values in Finance Apps)
Financial applications often require calculating totals, such as sum of transactions.
Example: Sum of All Product Prices
double totalCost = products.stream()
.mapToDouble(Product::getPrice)
.sum();
System.out.println("Total Cost: ₹" + totalCost);
📌 Key Takeaway:
✔ Use mapToDouble()
and sum()
for aggregating numerical values.
4️⃣ Finding Max and Min Values (Finding the Most Expensive Product)
Stream API can be used to find the highest and lowest values efficiently.
Example: Finding the Most Expensive Product
Optional<Product> expensiveProduct = products.stream()
.max(Comparator.comparing(Product::getPrice));
System.out.println(expensiveProduct.get()); // Output: Laptop - ₹70000
📌 Key Takeaway:
✔ Use max()
and min()
to find extreme values in collections.
5️⃣ Removing Duplicates from a List (Avoid Duplicate Entries in a System)
Duplicate data is common in database queries and user inputs.
Example: Removing Duplicate Products
List<String> uniqueProductNames = products.stream()
.map(Product::getName)
.distinct()
.collect(Collectors.toList());
System.out.println(uniqueProductNames);
📌 Key Takeaway:
✔ Use distinct()
to remove duplicate elements.
6️⃣ Grouping Data (Categorizing Employees by Department)
In HR applications, grouping employees by department is a common requirement.
Example: Group Employees by Department
import java.util.stream.Collectors;
class Employee {
private String name;
private String department;
public Employee(String name, String department) {
this.name = name;
this.department = department;
}
public String getDepartment() { return department; }
public String getName() { return name; }
}
List<Employee> employees = Arrays.asList(
new Employee("Raj", "IT"),
new Employee("Priya", "HR"),
new Employee("Amit", "IT"),
new Employee("Neha", "Finance")
);
Map<String, List<Employee>> employeesByDept = employees.stream()
.collect(Collectors.groupingBy(Employee::getDepartment));
System.out.println(employeesByDept);
📌 Key Takeaway:
✔ Use groupingBy()
for categorizing data based on a specific field.
7️⃣ Processing Large Data in Parallel (Performance Optimization)
Stream API provides parallel processing to improve performance in CPU-intensive tasks.
Example: Processing a Large List in Parallel
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
numbers.parallelStream()
.forEach(n -> System.out.println(Thread.currentThread().getName() + " - " + n));
📌 Key Takeaway:
✔ Use parallelStream()
to speed up execution on multi-core processors.
8️⃣ Reading a File and Filtering Data (Log File Analysis)
Stream API is useful for processing large log files.
Example: Read a File and Filter Lines Containing “ERROR”
import java.nio.file.*;
import java.io.IOException;
import java.util.stream.Stream;
public class FileProcessing {
public static void main(String[] args) throws IOException {
Path path = Paths.get("server.log");
try (Stream<String> lines = Files.lines(path)) {
lines.filter(line -> line.contains("ERROR"))
.forEach(System.out::println);
}
}
}
📌 Key Takeaway:
✔ Use Files.lines()
to read large files efficiently using streams.
9️⃣ Finding the First Matching Element (Searching in a Database Result Set)
Sometimes, we need to find the first matching record instead of filtering the entire collection.
Example: Finding the First Expensive Product Above ₹5000
Optional<Product> expensiveProduct = products.stream()
.filter(p -> p.getPrice() > 5000)
.findFirst();
System.out.println(expensiveProduct.get());
📌 Key Takeaway:
✔ Use findFirst()
to return the first matching element.
🔟 Using Java 8 Stream API for Entity to DTO Conversion — A Complete Guide
One of the common real-world scenarios in software development is converting an Entity (Customer) to a DTO (Data Transfer Object).
In this example, we will compare the traditional approach (pre-Java 8) with the Stream API approach for converting Customer entities into CustomerDTOs.
Customer Entity and DTO Class Definition
Before implementing the conversion logic, let’s define our Customer entity and CustomerDTO.
📌 Customer Entity
public class Customer {
private int id;
private String firstName;
private String lastName;
public Customer(int id, String firstName, String lastName) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
}
public int getId() { return id; }
public String getFirstName() { return firstName; }
public String getLastName() { return lastName; }
}
📌 CustomerDTO
public class CustomerDTO {
private int id;
private String firstName;
private String lastName;
public CustomerDTO(int id, String firstName, String lastName) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
}
public int getId() { return id; }
public String getFirstName() { return firstName; }
public String getLastName() { return lastName; }
}
Entity to DTO Conversion: Java 8 Stream API Approach
Java 8 Streams allow declarative programming to achieve the same goal in fewer lines.
import java.util.*;
import java.util.stream.Collectors;
public class Java8StreamAPIDemo {
public static void main(String[] args) {
Set<Customer> customers = new HashSet<>();
customers.add(new Customer(100, "John", "Doe"));
customers.add(new Customer(200, "Jane", "Smith"));
customers.add(new Customer(300, "Mike", "Brown"));
// Convert Entity to DTO using Stream API
Set<CustomerDTO> customerDTOs = customers.stream()
.map(c -> new CustomerDTO(c.getId(), c.getFirstName(), c.getLastName()))
.collect(Collectors.toSet());
// Display DTOs
customerDTOs.forEach(dto -> System.out.println(dto.getId() + " - " + dto.getFirstName()));
}
}
✅ Pros:
✔ More Readable & Concise
✔ Improved Performance with Parallel Streams
✔ Thread-Safe Execution
Converting List of Customers to List of CustomerDTOs
A List conversion follows the same logic as a Set.
import java.util.*;
import java.util.stream.Collectors;
public class ConvertListDemo {
public static void main(String[] args) {
List<Customer> customerList = Arrays.asList(
new Customer(101, "Alice", "Johnson"),
new Customer(102, "Bob", "Davis"),
new Customer(103, "Charlie", "Miller")
);
// Convert List<Customer> to List<CustomerDTO>
List<CustomerDTO> dtoList = customerList.stream()
.map(c -> new CustomerDTO(c.getId(), c.getFirstName(), c.getLastName()))
.collect(Collectors.toList());
// Display DTO List
dtoList.forEach(dto -> System.out.println(dto.getId() + " - " + dto.getFirstName()));
}
}
📌 Key Takeaway:
✔ Use toList()
for Lists instead of toSet()
.
Using parallelStream()
for Performance Optimization
For large datasets, parallelStream()
allows parallel execution for faster processing.
List<CustomerDTO> dtoList = customerList.parallelStream()
.map(c -> new CustomerDTO(c.getId(), c.getFirstName(), c.getLastName()))
.collect(Collectors.toList());
📌 Key Takeaway:
✔ Use parallelStream()
for large lists to improve performance.
🚀 Conclusion: Why Use Stream API in Real Projects?
✔ Reduces Boilerplate Code — No need for explicit loops
✔ Improves Performance — Supports parallel execution
✔ Optimized for Big Data — Handles large datasets efficiently
✔ Functional & Declarative — More readable and maintainable
Stream API provides a cleaner, more readable, and optimized approach to transforming entities into DTOs. It is recommended for modern Java applications to improve maintainability and performance.
🚀 Master these real-world use cases to leverage Java Streams effectively in your projects! 💡
Comments
Post a Comment
Leave Comment