Backend Development 27 min read

Mastering Java 8 Stream API: 20 Real‑World Examples

This tutorial walks through Java 8 Stream and Lambda features, explaining stream concepts, intermediate and terminal operations, and demonstrating twenty practical examples—including creation, filtering, mapping, reduction, collection, sorting, and combining—using an employee class to illustrate each operation.

macrozheng
macrozheng
macrozheng
Mastering Java 8 Stream API: 20 Real‑World Examples

What Is a Stream?

In Java 8, a

Stream

treats a collection of elements as a flow, allowing operations such as filtering, sorting, and aggregation via the Stream API.

Stream operations are divided into two categories:

Intermediate operations that return a new stream and can be chained.

Terminal operations that produce a final result (a collection, a value, or a side effect) and close the stream.

Key characteristics of streams:

Streams do not store data; they compute results on demand.

Streams do not modify the source; they produce new collections or values.

Streams are lazy; intermediate operations execute only when a terminal operation is invoked.

Creating Streams

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

<code>List&lt;String&gt; list = Arrays.asList("a", "b", "c");
Stream&lt;String&gt; stream = list.stream(); // sequential
Stream&lt;String&gt; parallel = list.parallelStream(); // parallel</code>
<code>int[] array = {1,3,5,6,8};
IntStream stream = Arrays.stream(array);
</code>
<code>Stream&lt;Integer&gt; stream = Stream.of(1,2,3,4,5,6);
Stream&lt;Integer&gt; iter = Stream.iterate(0, x -> x + 3).limit(4);
Stream&lt;Double&gt; gen = Stream.generate(Math::random).limit(3);
</code>
0 3 6 9 0.6796156909271994 0.1914314208854283 0.8116932592396652

Sequential streams process elements in order on the main thread, while parallel streams split the work across multiple threads when ordering is not required.

<code>Optional&lt;Integer&gt; findFirst = list.stream().parallel().filter(x -> x > 6).findFirst();
</code>

Employee Class Used in the Examples

<code>class Person {
  private String name; // name
  private int salary;   // salary
  private int age;      // age
  private String sex;   // gender
  private String area;  // region

  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
}
</code>

3.1 Traversal / Matching (forEach / find / anyMatch)

<code>List&lt;Integer&gt; list = Arrays.asList(7,6,9,3,8,2,1);
list.stream().filter(x -> x > 6).forEach(System.out::println);
Optional&lt;Integer&gt; first = list.stream().filter(x -> x > 6).findFirst();
Optional&lt;Integer&gt; any = list.parallelStream().filter(x -> x > 6).findAny();
boolean anyMatch = list.stream().anyMatch(x -> x < 6);
System.out.println("First: " + first.get());
System.out.println("Any: " + any.get());
System.out.println("Contains <6: " + anyMatch);
</code>

3.2 Filtering (filter)

<code>List&lt;Integer&gt; list = Arrays.asList(6,7,3,8,1,2,9);
list.stream().filter(x -> x > 7).forEach(System.out::println);
</code>
8 9
<code>List&lt;Person&gt; personList = new ArrayList<>();
// add Person objects …
List&lt;String&gt; highEarners = personList.stream()
    .filter(p -> p.getSalary() > 8000)
    .map(Person::getName)
    .collect(Collectors.toList());
System.out.println("Names >8000: " + highEarners);
</code>
Names >8000: [Tom, Anni, Owen]

3.3 Aggregation (max / min / count)

<code>List&lt;String&gt; list = Arrays.asList("adnm","admmt","pot","xbangd","weoujgsd");
Optional&lt;String&gt; max = list.stream().max(Comparator.comparing(String::length));
System.out.println("Longest: " + max.get());
</code>
Longest: weoujgsd
<code>List&lt;Integer&gt; list = Arrays.asList(7,6,9,4,11,6);
Optional&lt;Integer&gt; max = list.stream().max(Integer::compareTo);
System.out.println("Max: " + max.get());
</code>
Max: 11
<code>Optional&lt;Person&gt; maxSalary = personList.stream()
    .max(Comparator.comparingInt(Person::getSalary));
System.out.println("Highest salary: " + maxSalary.get().getSalary());
</code>
Highest salary: 9500
<code>List&lt;Integer&gt; list = Arrays.asList(7,6,4,8,2,11,9);
long count = list.stream().filter(x -> x > 6).count();
System.out.println("Count >6: " + count);
</code>
Count >6: 4

3.4 Mapping (map / flatMap)

<code>String[] arr = {"abcd","bcdd","defde","fTr"};
List&lt;String&gt; upper = Arrays.stream(arr)
    .map(String::toUpperCase)
    .collect(Collectors.toList());
System.out.println(upper);
</code>
[ABCD, BCDD, DEFDE, FTR]
<code>List&lt;Integer&gt; intList = Arrays.asList(1,3,5,7,9,11);
List&lt;Integer&gt; plus3 = intList.stream()
    .map(x -> x + 3)
    .collect(Collectors.toList());
System.out.println(plus3);
</code>
[4, 6, 8, 10, 12, 14]
<code>List&lt;Person&gt; personList = …;
List&lt;Person&gt; increased = personList.stream()
    .map(p -> {
        Person copy = new Person(p.getName(), 0, 0, null, null);
        copy.setSalary(p.getSalary() + 10000);
        return copy;
    })
    .collect(Collectors.toList());
System.out.println("Before: " + personList.get(0).getSalary());
System.out.println("After: " + increased.get(0).getSalary());
</code>
Before: 8900 After: 18900
<code>List&lt;String&gt; list = Arrays.asList("m,k,l,a", "1,3,5,7");
List&lt;String&gt; flat = list.stream()
    .flatMap(s -> Arrays.stream(s.split(",")))
    .collect(Collectors.toList());
System.out.println(flat);
</code>
[m, k, l, a, 1, 3, 5, 7]

3.5 Reduction (reduce)

<code>List&lt;Integer&gt; list = Arrays.asList(1,3,2,8,11,4);
Optional&lt;Integer&gt; sum = list.stream().reduce((a,b) -> a + b);
Optional&lt;Integer&gt; product = list.stream().reduce((a,b) -> a * b);
Optional&lt;Integer&gt; max = list.stream().reduce((a,b) -> a > b ? a : b);
System.out.println("Sum: " + sum.get());
System.out.println("Product: " + product.get());
System.out.println("Max: " + max.get());
</code>
Sum: 29 Product: 2112 Max: 11
<code>Integer taxSum = personList.stream()
    .collect(Collectors.reducing(0, Person::getSalary, (a,b) -> a + b - 5000));
System.out.println("Taxed sum: " + taxSum);
</code>
Taxed sum: 8700

3.6 Collecting (collect)

<code>List&lt;Integer&gt; list = Arrays.asList(1,6,3,4,6,7,9,6,20);
List&lt;Integer&gt; evens = list.stream()
    .filter(x -> x % 2 == 0)
    .collect(Collectors.toList());
Set&lt;Integer&gt; evenSet = list.stream()
    .filter(x -> x % 2 == 0)
    .collect(Collectors.toSet());
Map&lt;String, Person&gt; map = personList.stream()
    .filter(p -> p.getSalary() > 8000)
    .collect(Collectors.toMap(Person::getName, p -> p));
System.out.println(evens);
System.out.println(evenSet);
System.out.println(map);
</code>
toList: [6, 4, 6, 6, 20] toSet: [4, 20, 6] toMap: {Tom=..., Anni=...}
<code>Long count = personList.stream().collect(Collectors.counting());
Double avg = personList.stream().collect(Collectors.averagingDouble(Person::getSalary));
Integer sum = personList.stream().collect(Collectors.summingInt(Person::getSalary));
DoubleSummaryStatistics stats = personList.stream().collect(Collectors.summarizingDouble(Person::getSalary));
System.out.println("Count: " + count);
System.out.println("Avg: " + avg);
System.out.println("Sum: " + sum);
System.out.println("Stats: " + stats);
</code>
Count: 3 Avg: 7900.0 Sum: 23700 Stats: DoubleSummaryStatistics{count=3, sum=23700.0, min=7000.0, average=7900.0, max=8900.0}
<code>Map&lt;Boolean, List&lt;Person&gt;&gt; partition = personList.stream()
    .collect(Collectors.partitioningBy(p -> p.getSalary() > 8000));
Map&lt;String, List&lt;Person&gt;&gt; bySex = personList.stream()
    .collect(Collectors.groupingBy(Person::getSex));
Map&lt;String, Map&lt;String, List&lt;Person&gt;&gt;&gt; bySexArea = personList.stream()
    .collect(Collectors.groupingBy(Person::getSex, Collectors.groupingBy(Person::getArea)));
System.out.println(partition);
System.out.println(bySex);
System.out.println(bySexArea);
</code>
partition: {false=[...], true=[...]} bySex: {female=[...], male=[...]} bySexArea: {female={New York=[...], Washington=[...]}, male={New York=[...], Washington=[...]}}
<code>String names = personList.stream()
    .map(Person::getName)
    .collect(Collectors.joining(","));
System.out.println("Names: " + names);
</code>
Names: Tom,Jack,Lily

3.7 Sorting (sorted)

<code>List&lt;String&gt; bySalary = personList.stream()
    .sorted(Comparator.comparing(Person::getSalary))
    .map(Person::getName)
    .collect(Collectors.toList());
List&lt;String&gt; bySalaryDesc = personList.stream()
    .sorted(Comparator.comparing(Person::getSalary).reversed())
    .map(Person::getName)
    .collect(Collectors.toList());
List&lt;String&gt; bySalaryThenAge = personList.stream()
    .sorted(Comparator.comparing(Person::getSalary).thenComparing(Person::getAge))
    .map(Person::getName)
    .collect(Collectors.toList());
List&lt;String&gt; custom = personList.stream()
    .sorted((p1,p2) -> {
        if (p1.getSalary() == p2.getSalary()) {
            return p2.getAge() - p1.getAge();
        } else {
            return p2.getSalary() - p1.getSalary();
        }
    })
    .map(Person::getName)
    .collect(Collectors.toList());
System.out.println(bySalary);
System.out.println(bySalaryDesc);
System.out.println(bySalaryThenAge);
System.out.println(custom);
</code>
bySalary: [Lily, Tom, Sherry, Jack, Alisa] bySalaryDesc: [Sherry, Jack, Alisa, Tom, Lily] bySalaryThenAge: [Lily, Tom, Sherry, Jack, Alisa] custom: [Alisa, Jack, Sherry, Tom, Lily]

3.8 Extraction / Combination

<code>String[] arr1 = {"a","b","c","d"};
String[] arr2 = {"d","e","f","g"};
List&lt;String&gt; merged = Stream.concat(Stream.of(arr1), Stream.of(arr2))
    .distinct()
    .collect(Collectors.toList());
List&lt;Integer&gt; limited = Stream.iterate(1, x -> x + 2)
    .limit(10)
    .collect(Collectors.toList());
List&lt;Integer&gt; skipped = Stream.iterate(1, x -> x + 2)
    .skip(1)
    .limit(5)
    .collect(Collectors.toList());
System.out.println("Merged: " + merged);
System.out.println("Limited: " + limited);
System.out.println("Skipped: " + skipped);
</code>
Merged: [a, b, c, d, e, f, g] Limited: [1, 3, 5, 7, 9, 11, 13, 15, 17, 19] Skipped: [3, 5, 7, 9, 11]

These examples cover the essential operations of Java 8 streams, providing a solid foundation for functional-style processing of collections.

JavaData Processinglambdafunctional programmingCollectionsStream APIJava 8
macrozheng
Written by

macrozheng

Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.

0 followers
Reader feedback

How this landed with the community

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