Master Java Stream API: 20 Real‑World Examples and Best Practices

This tutorial walks through Java 8 Stream fundamentals, covering creation, intermediate operations (filter, map, flatMap, reduce), terminal actions, collectors, grouping, sorting, and parallel streams, illustrated with 20 practical code examples that transform and analyze collections of objects such as employee records.

Java Architect Essentials
Java Architect Essentials
Java Architect Essentials
Master Java Stream API: 20 Real‑World Examples and Best Practices

This article demonstrates how the Java 8 Stream API, together with lambda expressions, provides a declarative way to process collections.

Creating Streams

Streams can be obtained from collections, arrays or static factory methods:

List<String> list = Arrays.asList("a", "b", "c");
Stream<String> s1 = list.stream();
Stream<String> s2 = Stream.of("x", "y", "z");
IntStream intStream = IntStream.of(1, 2, 3);

Intermediate Operations

Filtering

Retain only elements that satisfy a predicate:

List<Integer> numbers = Arrays.asList(1, 6, 7, 8, 2);
List<Integer> greaterThanSix = numbers.stream()
    .filter(x -> x > 6)
    .collect(Collectors.toList()); // [7, 8]

Mapping and FlatMapping

Transform each element ( map) or replace an element with another stream and flatten the result ( flatMap).

String[] words = {"abcd", "bcdd", "defde", "fTr"};
List<String> upper = Arrays.stream(words)
    .map(String::toUpperCase)
    .collect(Collectors.toList()); // [ABCD, BCDD, DEFDE, FTR]

List<String> csv = Arrays.asList("m,k,l,a", "1,3,5,7");
List<String> flat = csv.stream()
    .flatMap(s -> Arrays.stream(s.split(",")))
    .collect(Collectors.toList()); // [m, k, l, a, 1, 3, 5, 7]

Distinct, Limit, Skip

Remove duplicates, limit the number of processed elements, or skip a prefix:

Stream<String> distinct = Stream.concat(Stream.of("a", "b"), Stream.of("b", "c"))
    .distinct(); // [a, b, c]

List<Integer> firstTen = Stream.iterate(1, n -> n + 2)
    .limit(10)
    .collect(Collectors.toList()); // [1,3,5,7,9,11,13,15,17,19]

List<Integer> afterSkip = Stream.iterate(1, n -> n + 2)
    .skip(1)
    .limit(5)
    .collect(Collectors.toList()); // [3,5,7,9,11]

Sorting

Natural order or custom comparator:

List<Person> people = ...;
List<String> bySalaryDesc = people.stream()
    .sorted(Comparator.comparing(Person::getSalary).reversed())
    .map(Person::getName)
    .collect(Collectors.toList());

Terminal Operations

Collecting

Gather stream elements into containers or aggregate values using Collectors:

// toList / toSet
List<Integer> evens = numbers.stream()
    .filter(x -> x % 2 == 0)
    .collect(Collectors.toList());
Set<Integer> evenSet = numbers.stream()
    .filter(x -> x % 2 == 0)
    .collect(Collectors.toSet());

// toMap – map a key to a value
Map<String, Person> highEarners = people.stream()
    .filter(p -> p.getSalary() > 8000)
    .collect(Collectors.toMap(Person::getName, p -> p));

Statistical Summaries

Built‑in collectors for counting, averaging, summing and full statistics:

long count = people.stream().collect(Collectors.counting());
double avgSalary = people.stream().collect(Collectors.averagingDouble(Person::getSalary));
int totalSalary = people.stream().collect(Collectors.summingInt(Person::getSalary));
IntSummaryStatistics stats = people.stream().collect(Collectors.summarizingInt(Person::getSalary));

Grouping and Partitioning

Group elements by a key or partition them by a boolean predicate:

// Partition by salary > 8000
Map<Boolean, List<Person>> byHighSalary = people.stream()
    .collect(Collectors.partitioningBy(p -> p.getSalary() > 8000));

// Group by gender
Map<String, List<Person>> byGender = people.stream()
    .collect(Collectors.groupingBy(Person::getSex));

// Multi‑level grouping: gender then area
Map<String, Map<String, List<Person>>> byGenderArea =
    people.stream().collect(Collectors.groupingBy(Person::getSex,
        Collectors.groupingBy(Person::getArea)));

Joining

Concatenate string representations with a delimiter:

String names = people.stream()
    .map(Person::getName)
    .collect(Collectors.joining(",")); // e.g. "Tom,Jack,Lily"

Reducing

Custom reduction using reduce or Collectors.reducing:

int sum = numbers.stream().reduce(0, Integer::sum);
Optional<Integer> max = numbers.stream().reduce(Integer::max);

// Example with a custom accumulator
Integer netSalarySum = people.stream()
    .collect(Collectors.reducing(0, Person::getSalary, (s, sal) -> s + sal - 5000));

Parallel Streams

Convert a sequential stream to parallel for potential performance gains on large data sets:

Optional<Integer> firstMatch = numbers.parallelStream()
    .filter(x -> x > 6)
    .findFirst();

Employee Example

A simple Person class is used throughout the examples:

public class Person {
    private String name;
    private int salary;
    private int age;
    private String sex;
    private String area;

    public Person(String name, int salary, int age, String sex, String area) {
        this.name = name;
        this.salary = salary;
        this.age = age;
        this.sex = sex;
        this.area = area;
    }
    // getters and setters omitted for brevity
}

Typical operations demonstrated with this class include:

Filtering employees with salary > 8000 and collecting the result.

Finding the employee with the highest salary using max or sorted.

Increasing every employee's salary by a fixed amount (both immutable and mutable approaches).

Collecting all employee names into a comma‑separated string.

Grouping by gender, by area, and by the combination of gender + area.

Partitioning by whether salary exceeds a threshold.

Summary

By leveraging the Stream API you can replace verbose loops with concise, readable pipelines that support lazy evaluation, parallel execution, and a rich set of built‑in collectors for aggregation, grouping, and reduction.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Javadata-processingfunctional programmingCollectionsStream API
Java Architect Essentials
Written by

Java Architect Essentials

Committed to sharing quality articles and tutorials to help Java programmers progress from junior to mid-level to senior architect. We curate high-quality learning resources, interview questions, videos, and projects from across the internet to help you systematically improve your Java architecture skills. Follow and reply '1024' to get Java programming resources. Learn together, grow together.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.