Practical Examples
Real-World Stream Processing Scenarios
class Employee {
private String name;
private double salary;
private Department department;
// Constructor, getters, setters
}
// Filter high-performing employees
List<Employee> topPerformers = employees.stream()
.filter(e -> e.getSalary() > 50000)
.filter(e -> e.getDepartment() == Department.ENGINEERING)
.collect(Collectors.toList());
2. Complex Data Aggregation
graph TD
A[Raw Data] --> B[Filter]
B --> C[Group]
C --> D[Aggregate]
D --> E[Result]
Department Salary Analysis
// Calculate average salary by department
Map<Department, Double> avgSalaryByDept = employees.stream()
.collect(Collectors.groupingBy(
Employee::getDepartment,
Collectors.averagingDouble(Employee::getSalary)
));
Mapping and Extracting
// Extract unique names
Set<String> uniqueNames = employees.stream()
.map(Employee::getName)
.collect(Collectors.toSet());
// Create name-salary map
Map<String, Double> nameSalaryMap = employees.stream()
.collect(Collectors.toMap(
Employee::getName,
Employee::getSalary
));
4. Parallel Processing
| Processing Type |
Characteristics |
Use Case |
| Sequential |
Single-threaded |
Small datasets |
| Parallel |
Multi-threaded |
Large datasets |
// Parallel processing of large employee list
double totalSalary = employees.parallelStream()
.mapToDouble(Employee::getSalary)
.sum();
5. Advanced Filtering Techniques
// Complex conditional filtering
List<Employee> seniorEngineers = employees.stream()
.filter(e -> e.getDepartment() == Department.ENGINEERING)
.filter(e -> e.getExperience() > 5)
.filter(e -> e.getSalary() > 75000)
.collect(Collectors.toList());
6. Custom Collectors
// Custom collector for finding top N employees
Collector<Employee, ?, List<Employee>> topNCollector =
Collectors.collectingAndThen(
Collectors.toList(),
list -> list.stream()
.sorted(Comparator.comparing(Employee::getSalary).reversed())
.limit(5)
.collect(Collectors.toList())
);
List<Employee> topFiveEmployees = employees.stream()
.collect(topNCollector);
- Use appropriate stream operations
- Avoid unnecessary intermediate operations
- Consider data size and complexity
- Profile and benchmark your stream processing
Error Handling in Streams
// Safe processing with exception handling
List<String> processedData = rawData.stream()
.map(this::safeProcessing)
.filter(Optional::isPresent)
.map(Optional::get)
.collect(Collectors.toList());
Conclusion
Streams provide powerful, flexible data processing capabilities. LabEx recommends continuous practice to master these techniques effectively.