SyntaxStudy
Sign Up
Java Optional and Stream Terminal Operations
Java Beginner 1 min read

Optional and Stream Terminal Operations

Optional is a container object that may or may not contain a non-null value. It was designed to replace null returns from methods, making the possibility of absence explicit in the type system and forcing callers to handle it. You create an Optional with Optional.of() (throws NullPointerException if null), Optional.ofNullable() (accepts null), or Optional.empty(). Accessing the value safely is done with ifPresent(), orElse(), orElseGet(), orElseThrow(), or map()/flatMap()/filter() for chaining transformations. Stream terminal operations that may produce no result return Optional: findFirst(), findAny(), min(), max(), and the single-argument form of reduce() all return Optional. This forces you to consider the empty-stream case. count() returns a long, anyMatch()/allMatch()/noneMatch() return boolean, and forEach() returns void. Terminal operations consume the stream and it cannot be reused afterwards. Streams can also be created from sources other than collections: Stream.of(), Stream.iterate(), Stream.generate(), Arrays.stream(), Files.lines(), and String.chars(). Stream.iterate() is particularly useful for producing sequences, and Stream.generate() with a Supplier can produce infinite streams that are consumed lazily with limit().
Example
import java.util.*;
import java.util.stream.*;

public class OptionalAndTerminalDemo {
    record Product(String name, double price, int stock) {}

    public static void main(String[] args) {
        List<Product> products = List.of(
            new Product("Laptop",  999.99, 5),
            new Product("Mouse",    29.99, 0),
            new Product("Keyboard", 79.99, 12),
            new Product("Monitor", 349.99, 3)
        );

        // findFirst returns Optional
        Optional<Product> cheapest = products.stream()
            .filter(p -> p.stock() > 0)
            .min(Comparator.comparingDouble(Product::price));

        cheapest.ifPresent(p ->
            System.out.println("Cheapest in stock: " + p.name() + " $" + p.price()));

        // orElse / orElseThrow
        String name = products.stream()
            .filter(p -> p.price() > 500 && p.stock() > 0)
            .map(Product::name)
            .findFirst()
            .orElse("No expensive item in stock");
        System.out.println(name);

        // anyMatch / allMatch / noneMatch
        boolean anyOutOfStock = products.stream().anyMatch(p -> p.stock() == 0);
        boolean allHavePrice  = products.stream().allMatch(p -> p.price() > 0);
        System.out.println("Any out of stock: " + anyOutOfStock);
        System.out.println("All have price:   " + allHavePrice);

        // Stream.iterate — first 8 powers of 2
        List<Integer> powers = Stream.iterate(1, n -> n * 2)
            .limit(8)
            .collect(Collectors.toList());
        System.out.println("Powers of 2: " + powers);

        // Stream.generate — 5 random doubles
        Stream.generate(Math::random)
            .limit(5)
            .map(d -> String.format("%.4f", d))
            .forEach(System.out::println);
    }
}