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!
                        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.

On this page