Dr. Vatsal Shah
Subject Material

Java · Collections · Topic 10

Streams API

Build declarative Java data pipelines with stream creation, transformation, reduction, matching, numeric streams, and collectors.

Topic progress · 1 of 30 sections

Step 1 of 30

10.1 Introduction

Learning objective

Explain declarative stream processing and its common operations.

StreamsIntroductionDemo.java
import java.util.Arrays;
import java.util.List;
public class StreamsIntroductionDemo {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(10,15,20,25,30);
        numbers.stream().filter(n -> n % 2 == 0).forEach(System.out::println);
    }
}
Output
10
20
30

Stream operations

  • Filtering
  • Transforming
  • Sorting
  • Removing duplicates
  • Counting
  • Aggregation
  • Grouping
  • Collecting
Check your understanding: Which operation selects elements satisfying a condition?

filter().

Step 2 of 30

10.2 Stream Is Not a Data Structure

Learning objective

Distinguish processing from storage and observe source immutability.

StreamSourceDemo.java
import java.util.*;
import java.util.stream.Collectors;
public class StreamSourceDemo {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(5,2,8,1);
        List<Integer> sorted = numbers.stream().sorted().collect(Collectors.toList());
        System.out.println(numbers);
        System.out.println(sorted);
    }
}
Output
[5, 2, 8, 1]
[1, 2, 5, 8]

Possible sources

  • Collection
  • Array
  • File
  • Generated values
Check your understanding: Does a stream itself store the elements?

No.

Step 3 of 30

10.3 Stream Pipeline

Learning objective

Identify source, intermediate operations, and a terminal operation.

StreamPipelineDemo.java
import java.util.*;
import java.util.stream.Collectors;
public class StreamPipelineDemo {
    public static void main(String[] args) {
        List<String> names = Arrays.asList("Java", "C", "Python", "Go");
        List<String> result = names.stream()
            .filter(name -> name.length() > 3)
            .map(String::toUpperCase)
            .sorted()
            .collect(Collectors.toList());
        System.out.println(result);
    }
}
Output
[JAVA, PYTHON]
Pipeline stages
StageRoleExamples
SourceProvides datanames.stream()
IntermediateTransforms or filtersfilter(), map(), sorted()
TerminalProduces result or actioncollect(), forEach(), count(), reduce()
Check your understanding: Which operation completes the shown pipeline?

collect().

Step 4 of 30

10.4 Creating Streams

Learning objective

Create streams from collections, arrays, values, generators, and iterative sequences.

StreamCreationDemo.java
import java.util.*;
import java.util.stream.*;
public class StreamCreationDemo {
    public static void main(String[] args) {
        List<String> names = Arrays.asList("Amit", "Neha");
        System.out.println(names.stream().count());
        System.out.println(Arrays.stream(new String[]{"Java","Python"}).count());
        System.out.println(Stream.of(10,20,30,40).count());
        Stream.iterate(1, n -> n + 1).limit(5).forEach(System.out::println);
    }
}
Output
2
2
4
1
2
3
4
5
Other creation forms
Stream<String> empty = Stream.empty();
Stream<Double> random = Stream.generate(Math::random).limit(5);
Check your understanding: Why should generate() usually be followed by limit() in examples?

generate() is otherwise unbounded.

Step 5 of 30

10.5 Intermediate Operations

Learning objective

Recognize lazy operations that return another Stream.

Important intermediate operations

  • filter()
  • map()
  • flatMap()
  • sorted()
  • distinct()
  • limit()
  • skip()
  • peek()
Check your understanding: Does filter() immediately traverse the source by itself?

No.

Step 6 of 30

10.6 filter()

Learning objective

Select elements with a Predicate.

FilterDemo.java
import java.util.*;
public class FilterDemo {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(10,15,20,25,30);
        numbers.stream().filter(n -> n > 20).forEach(System.out::println);
    }
}
Output
25
30
Check your understanding: Which values greater than 20 remain from 10,15,20,25,30?

25 and 30.

Step 7 of 30

10.7 map()

Learning objective

Transform every stream element using a Function.

MapStreamDemo.java
import java.util.*;
public class MapStreamDemo {
    public static void main(String[] args) {
        Arrays.asList(1,2,3,4).stream().map(n -> n*n).forEach(System.out::println);
        Arrays.asList("Java","Python").stream().map(String::toUpperCase).forEach(System.out::println);
    }
}
Output
1
4
9
16
JAVA
PYTHON
Check your understanding: What are the squares of 1,2,3,4?

1,4,9,16.

Step 8 of 30

10.8 flatMap()

Learning objective

Flatten nested element streams into one stream.

FlatMapDemo.java
import java.util.*;
import java.util.stream.Collectors;
public class FlatMapDemo {
    public static void main(String[] args) {
        List<List<Integer>> lists = Arrays.asList(
            Arrays.asList(1,2), Arrays.asList(3,4), Arrays.asList(5,6));
        List<Integer> result = lists.stream().flatMap(List::stream).collect(Collectors.toList());
        System.out.println(result);
    }
}
Output
[1, 2, 3, 4, 5, 6]
Check your understanding: What is the flattened form of [1,2], [3,4], [5,6]?

[1,2,3,4,5,6].

Step 9 of 30

10.9 sorted()

Learning objective

Sort stream elements naturally or with a Comparator.

Sorting forms
numbers.stream().sorted();
numbers.stream().sorted(Comparator.reverseOrder());
names.stream().sorted(Comparator.comparingInt(String::length));
Check your understanding: How is descending numeric order requested?

sorted(Comparator.reverseOrder()).

Step 10 of 30

10.10 distinct()

Learning objective

Remove duplicates using object equality.

DistinctDemo.java
import java.util.*;
public class DistinctDemo {
    public static void main(String[] args) {
        Arrays.asList(10,20,10,30,20).stream().distinct().forEach(System.out::println);
    }
}
Output
10
20
30
Check your understanding: What remains from 10,20,10,30,20?

10,20,30 in encounter order.

Step 11 of 30

10.11 limit()

Learning objective

Take at most the first n encountered elements.

Take three
numbers.stream().limit(3).forEach(System.out::println);
Check your understanding: How many elements can limit(3) emit?

At most three.

Step 12 of 30

10.12 skip()

Learning objective

Ignore the first n elements and combine skip with limit for pages.

Skip and paginate
numbers.stream().skip(2).forEach(System.out::println);
numbers.stream().skip(5).limit(5).forEach(System.out::println);
Check your understanding: What does skip(5).limit(5) select?

Up to five elements after ignoring the first five.

Step 13 of 30

10.13 peek()

Learning objective

Observe elements while they continue through a pipeline.

Observe filtered values
numbers.stream()
    .filter(n -> n % 2 == 0)
    .peek(n -> System.out.println("Filtered: " + n))
    .map(n -> n * n)
    .forEach(System.out::println);
Check your understanding: Does peek terminate a stream?

No.

Step 14 of 30

10.14 Terminal Operations

Learning objective

Identify operations that consume and close a pipeline.

Terminal operations

  • forEach()
  • collect()
  • reduce()
  • count()
  • min()
  • max()
  • anyMatch()
  • allMatch()
  • noneMatch()
  • findFirst()
  • findAny()
Check your understanding: Which terminal operation counts elements?

count().

Step 15 of 30

10.15 forEach()

Learning objective

Perform an action for every consumed element.

Print every element
names.stream().forEach(System.out::println);
Check your understanding: What method reference prints each name?

System.out::println.

Step 16 of 30

10.16 collect()

Learning objective

Gather stream elements into collection results.

CollectorsDemo.java
import java.util.*;
import java.util.stream.Collectors;
public class CollectorsDemo {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(10,15,20,25,30);
        List<Integer> evens = numbers.stream().filter(n -> n%2==0).collect(Collectors.toList());
        Set<Integer> unique = numbers.stream().collect(Collectors.toSet());
        System.out.println(evens);
        System.out.println(unique.size());
    }
}
Output
[10, 20, 30]
5
Check your understanding: Which collector produces a Set?

Collectors.toSet().

Step 17 of 30

10.17 count()

Learning objective

Count elements after optional filtering.

Count matching values
long count = numbers.stream().filter(n -> n > 20).count();
System.out.println(count); // 2
Check your understanding: How many values exceed 20 in 10,15,20,25,30?

Two.

Step 18 of 30

10.18 min() and max()

Learning objective

Find extreme elements with a Comparator.

Find extremes safely
Optional<Integer> minimum = numbers.stream().min(Integer::compareTo);
Optional<Integer> maximum = numbers.stream().max(Integer::compareTo);
minimum.ifPresent(System.out::println);
maximum.ifPresent(System.out::println);
Check your understanding: Why is Optional returned?

An empty stream has no minimum or maximum.

Step 19 of 30

10.19 Optional

Learning objective

Represent a result that may be absent and handle it safely.

Safe Optional use
Optional<Integer> result = numbers.stream().max(Integer::compareTo);
result.ifPresent(System.out::println);
int maximum = result.orElse(0);
Check your understanding: What does orElse(0) provide when no value exists?

The default value 0.

Step 20 of 30

10.20 reduce()

Learning objective

Combine all elements into one accumulated result.

ReduceDemo.java
import java.util.*;
public class ReduceDemo {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1,2,3,4);
        System.out.println("Sum: " + numbers.stream().reduce(0, Integer::sum));
        System.out.println("Product: " + numbers.stream().reduce(1, (a,b) -> a*b));
        List<String> names = Arrays.asList("Java","C","Database");
        System.out.println("Longest: " + names.stream()
            .reduce((a,b) -> a.length() >= b.length() ? a : b).orElse(""));
    }
}
Output
Sum: 10
Product: 24
Longest: Database
Check your understanding: What identity should a multiplication reduction use?

1.

Step 21 of 30

10.21 Matching Operations

Learning objective

Test whether any, all, or no elements satisfy a Predicate.

Matching methods
MethodMeaning
anyMatch()At least one element matches
allMatch()Every element matches
noneMatch()No element matches
Matching examples
boolean anyLarge = numbers.stream().anyMatch(n -> n > 50);
boolean allPositive = numbers.stream().allMatch(n -> n > 0);
boolean noneNegative = numbers.stream().noneMatch(n -> n < 0);
Check your understanding: Which method succeeds when no element is negative?

noneMatch(n -> n < 0).

Step 22 of 30

10.22 Finding Operations

Learning objective

Find the first or any matching element through Optional.

Find matching values
Optional<Integer> first = numbers.stream().filter(n -> n > 20).findFirst();
Optional<Integer> any = numbers.stream().filter(n -> n > 20).findAny();
Check your understanding: Which operation guarantees the first encountered match?

findFirst().

Step 23 of 30

10.23 Numeric Streams

Learning objective

Use primitive-specialized streams and understand range boundaries.

NumericStreamDemo.java
import java.util.stream.IntStream;
public class NumericStreamDemo {
    public static void main(String[] args) {
        System.out.println(IntStream.rangeClosed(1,10).sum());
        IntStream.range(1,5).forEach(System.out::print);
        System.out.println();
        IntStream.rangeClosed(1,5).forEach(System.out::print);
    }
}
Output
55
1234
12345
Check your understanding: Does IntStream.range(1,5) include 5?

No; rangeClosed(1,5) includes it.

Step 24 of 30

10.24 Calculations Using Numeric Streams

Learning objective

Map boxed numbers to IntStream for sum, average, and maximum.

NumericCalculationDemo.java
import java.util.*;
public class NumericCalculationDemo {
    public static void main(String[] args) {
        List<Integer> marks = Arrays.asList(70,80,90,60);
        System.out.println("Total: " + marks.stream().mapToInt(Integer::intValue).sum());
        System.out.println("Average: " + marks.stream().mapToInt(Integer::intValue).average().orElse(0));
        System.out.println("Maximum: " + marks.stream().mapToInt(Integer::intValue).max().orElse(0));
    }
}
Output
Total: 300
Average: 75.0
Maximum: 90
Check your understanding: What is the average of 70,80,90,60?

75.0.

Step 25 of 30

10.25 Collectors

Learning objective

Identify common reduction, aggregation, grouping, and partitioning collectors.

Important collectors

  • toList()
  • toSet()
  • joining()
  • groupingBy()
  • partitioningBy()
  • counting()
  • averagingInt()
  • summingInt()
Check your understanding: Which collector divides elements into true and false groups?

partitioningBy().

Step 26 of 30

10.26 Joining Strings

Learning objective

Combine text elements with delimiters and optional boundaries.

JoiningDemo.java
import java.util.*;
import java.util.stream.Collectors;
public class JoiningDemo {
    public static void main(String[] args) {
        List<String> names = Arrays.asList("Amit","Neha","Raj");
        System.out.println(names.stream().collect(Collectors.joining(", ")));
        System.out.println(names.stream().collect(Collectors.joining(", ", "[", "]")));
    }
}
Output
Amit, Neha, Raj
[Amit, Neha, Raj]
Check your understanding: What does joining(", ") produce for Amit, Neha, Raj?

Amit, Neha, Raj.

Step 27 of 30

10.27 Grouping Data

Learning objective

Group elements by a classifier key.

GroupingDemo.java
import java.util.*;
import java.util.stream.Collectors;
public class GroupingDemo {
    public static void main(String[] args) {
        List<String> names = Arrays.asList("Amit","Raj","Neha","Riya","Ankit");
        Map<Character,List<String>> grouped = names.stream()
            .collect(Collectors.groupingBy(name -> name.charAt(0), TreeMap::new, Collectors.toList()));
        System.out.println(grouped);
    }
}
Output
{A=[Amit, Ankit], N=[Neha], R=[Raj, Riya]}
Check your understanding: Which key groups Amit and Ankit together?

The character A.

Step 28 of 30

10.28 Partitioning Data

Learning objective

Divide elements into exactly two boolean groups.

PartitioningDemo.java
import java.util.*;
import java.util.stream.Collectors;
public class PartitioningDemo {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1,2,3,4,5,6);
        Map<Boolean,List<Integer>> result = numbers.stream()
            .collect(Collectors.partitioningBy(n -> n % 2 == 0));
        System.out.println(result);
    }
}
Output
{false=[1, 3, 5], true=[2, 4, 6]}
Check your understanding: Where are even values placed?

Under the true key.

Step 29 of 30

10.29 Stream Laziness

Learning objective

Demonstrate that intermediate work waits for terminal demand.

No terminal operation
numbers.stream().filter(number -> {
    System.out.println(number);
    return number % 2 == 0;
}); // no output
Terminal operation triggers work
numbers.stream()
    .filter(number -> { System.out.println(number); return number % 2 == 0; })
    .forEach(System.out::println);
Check your understanding: Why does a filter-only pipeline print nothing?

No terminal operation requests any elements.

Step 30 of 30

10.30 A Stream Cannot Be Reused

Learning objective

Create a fresh stream after a terminal operation.

Incorrect reuse
Stream<String> stream = names.stream();
stream.forEach(System.out::println);
// stream.count(); // IllegalStateException
Create a fresh stream
long count = names.stream().count();
Check your understanding: How should count() be performed after a previous traversal?

Call names.stream() again to create a new stream.