12. Streams, Spring & Patterns
Streams API, Spring Boot Core & GoF Design Patterns
Master Java Streams API, functional interfaces, Spring Boot Inversion of Control (IoC), Dependency Injection (DI), and GoF Design Patterns in Java.
π Functional Programming & The Streams API
Introduced in Java 8, the Streams API provides a declarative, functional pipeline for processing collections of data:
- Analogy: An Automated Water Filtration Pipeline & Smart Factory.
- Source (
Collection.stream()): Reservoir of un-filtered raw river water. - Intermediate Operations (
filter,map): Inline pipe filters and chemical treatment chambers. Water flows through lazilyβno filtering happens until the end faucet is opened! - Terminal Operation (
collect,reduce): The end kitchen faucet pouring clean filtered water into a glass. - Spring Boot IoC Container: An Automated Smart Building System. Instead of buying, wiring, and installing your own air conditioner (
new Service()), the building system automatically injects pre-configured AC units into your room (@Autowired) when you move in!
- Source (
Streams Processing Pipeline
β
Collection βββΊ Stream() βββΊ filter() βββΊ map() βββΊ collect(Collectors.toList())
(Source) (Assembly) (Lazy) (Lazy) (Terminal Trigger)import java.util.List;
import java.util.stream.Collectors;
public class StreamsDemo {
public static void main(String[] args) {
List<String> names = List.of("alice", "bob", "alexander", "charlie", "amanda");
// Declarative Streams Pipeline
List<String> result = names.stream()
.filter(name -> name.startsWith("a")) // Filter names starting with 'a'
.map(String::toUpperCase) // Transform to uppercase
.sorted() // Sort alphabetically
.collect(Collectors.toList()); // Terminal trigger
System.out.println("Filtered Names: " + result); // [ALEXANDER, ALICE, AMANDA]
}
}π Spring Boot Enterprise Core: IoC & Dependency Injection
Spring Boot is built around Inversion of Control (IoC) and Dependency Injection (DI):
Spring Boot IoC Container
β
βββββββββββββββββββββββββββββββββΌββββββββββββββββββββββββββββββββ
βΌ βΌ βΌ
@RestController @Service @Repository
(HTTP Endpoint Controller) (Business Logic Component) (Database Access Data Layer)// Spring Boot Component Architecture Example
public interface OrderRepository {
void saveOrder(String orderId);
}
// 1. Data Layer Component
@org.springframework.stereotype.Repository
class OrderRepositoryImpl implements OrderRepository {
@Override
public void saveOrder(String orderId) {
System.out.println("Persisted Order " + orderId + " into Postgres Database.");
}
}
// 2. Business Service Layer Component
@org.springframework.stereotype.Service
class OrderService {
private final OrderRepository repository;
// Constructor Dependency Injection (Spring automatically injects bean!)
@org.springframework.beans.factory.annotation.Autowired
public OrderService(OrderRepository repository) {
this.repository = repository;
}
public void processOrder(String orderId) {
System.out.println("Validating order logic...");
repository.saveOrder(orderId);
}
}ποΈ Essential Gang of Four (GoF) Design Patterns
1. Singleton Pattern (Bill Pugh Initialization-on-Demand Holder)
Provides thread-safe lazy initialization without synchronization overhead:
public class DatabaseConnectionPool {
private DatabaseConnectionPool() {} // Private Constructor
// Static Inner Holder Class (Loaded lazily on first access!)
private static class Holder {
private static final DatabaseConnectionPool INSTANCE = new DatabaseConnectionPool();
}
public static DatabaseConnectionPool getInstance() {
return Holder.INSTANCE;
}
}2. Builder Pattern
Simplifies object instantiation for complex classes with many optional attributes:
public class UserAccount {
private final String username;
private final String email;
private final boolean active;
private UserAccount(Builder builder) {
this.username = builder.username;
this.email = builder.email;
this.active = builder.active;
}
public static class Builder {
private String username;
private String email;
private boolean active = true;
public Builder username(String username) { this.username = username; return this; }
public Builder email(String email) { this.email = email; return this; }
public Builder active(boolean active) { this.active = active; return this; }
public UserAccount build() { return new UserAccount(this); }
}
public static void main(String[] args) {
UserAccount account = new UserAccount.Builder()
.username("john_doe")
.email("[email protected]")
.active(true)
.build();
System.out.println("Built Account for: " + account.username);
}
}β Conceptual Quizzes
Knowledge Check
What is the difference between intermediate and terminal operations in the Java Streams API?
Knowledge Check
Why is Constructor Injection preferred over @Autowired Field Injection in Spring Boot applications?
π» Practice Problems
Problem: Stream Aggregation & Grouping By
Given a list of Employee objects (name, department, salary), write a Java Stream pipeline using Collectors.groupingBy() to group employees by department and calculate average department salary.