Intermediate · Lambdas, streams and files · topic 38 of 60 · 30 min
Streams: filter, map and collect
Explanation
Why streams?
Many loops follow the same shape: go through items, keep some, transform them, combine the result. The Stream API (Java 8) lets you write that as a pipeline of named steps. The code reads like the requirement: "paid orders from Pune, their amounts, total".
record Order(String id, String city, double amount, boolean paid) {}
List<Order> orders = List.of(
new Order("O1", "Pune", 450, true),
new Order("O2", "Delhi", 1200, false),
new Order("O3", "Pune", 900, true),
new Order("O4", "Goa", 300, true));
// Loop version
double total = 0;
for (Order o : orders) if (o.paid() && o.city().equals("Pune")) total += o.amount();
// Stream version
double total2 = orders.stream()
.filter(Order::paid)
.filter(o -> o.city().equals("Pune"))
.mapToDouble(Order::amount)
.sum(); // 1350.0The three parts of a pipeline
- Source: list.stream(), Arrays.stream(array), Stream.of(a, b, c), IntStream.rangeClosed(1, 10), Files.lines(path).
- Intermediate operations (return a new stream, run lazily): filter, map, mapToInt/mapToDouble, flatMap, sorted, distinct, limit, skip, peek.
- One terminal operation (produces a result and runs the pipeline): toList, collect, count, sum, average, min, max, reduce, anyMatch, allMatch, findFirst, forEach.
List<String> topCities = orders.stream()
.filter(Order::paid)
.sorted(Comparator.comparingDouble(Order::amount).reversed())
.map(Order::city)
.distinct()
.limit(2)
.toList(); // [Pune, Goa] (toList: Java 16+, unmodifiable)
long unpaid = orders.stream().filter(o -> !o.paid()).count(); // 1
boolean anyBig = orders.stream().anyMatch(o -> o.amount() > 1000); // true
OptionalDouble avg = orders.stream().mapToDouble(Order::amount).average(); // OptionalDouble[712.5]
int sumOfSquares = IntStream.rangeClosed(1, 5).map(n -> n * n).sum(); // 55
double product = Stream.of(2.0, 3.0, 4.0).reduce(1.0, (a, b) -> a * b); // 24.0Lazy and single-use
Intermediate operations do nothing until a terminal operation is called; then each element flows through the whole pipeline. That allows short-circuiting: findFirst or limit stop as soon as they have enough. A stream can be consumed only once; calling a second terminal operation on the same stream throws IllegalStateException: stream has already been operated upon or closed.
Primitive streams
Stream<Integer> boxes every number. IntStream, LongStream and DoubleStream work on primitives and add sum, average, min, max and summaryStatistics. Switch with mapToInt/mapToDouble and back with boxed().
Need help?
Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.
Try:
Watch the lesson
Streams: filter, map and collect · 1/6
In this lesson you will process collections with streams.
Prefer a video by a teacher? Find free videos on “java streams tutorial filter map reduce collect” on YouTube ↗
In real life: Top 3 products by revenue
An e-commerce dashboard shows the three best-selling products of the day by revenue. A stream sorts the day's sales by revenue descending and takes three.
record Sale(String product, int qty, double price) { double revenue() { return qty * price; } }
List<String> top3 = sales.stream()
.sorted(Comparator.comparingDouble(Sale::revenue).reversed())
.limit(3)
.map(s -> s.product() + " (Rs " + s.revenue() + ")")
.toList();Practice (0/3 done)
What does this print? System.out.println(Stream.of(5, 2, 8, 2, 9).filter(n -> n > 2).distinct().sorted().toList());
The same pipeline in JavaScript, which runs here: write puneRevenue(orders) that returns the total amount of PAID orders from Pune, using filter, map and reduce (like Java's filter, mapToDouble and sum). Orders look like { id, city, amount, paid }.
Given a List<Order>(id, city, amount, paid), write stream pipelines that compute: (a) the number of unpaid orders, (b) the ids of the 2 biggest paid orders, (c) whether any order is above ₹5,000, (d) the average amount of paid orders (print "none" if there are none).
Quick quiz
Read more (free)
Related help
Before this, learn
This topic builds on these. If something here feels new, open them first.
Related topics
- Collectors: grouping and summarisingLambdas, streams and files · same module
- Lambdas and functional interfacesLambdas, streams and files · same module
- Collection operationsKotlin and Android App Development · Classes, objects and collections
- Loops: for, while, do-while and foreachC# and .NET · Decisions, loops and methods
- StreamsFlutter and Dart · Async Dart and packages
- Arrays and array methodsFrontend Web Development · JavaScript basics
Questions people ask about this
Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.
Which is a terminal operation?
Answer: count
count produces a result and runs the pipeline.
What happens if you call two terminal operations on the same stream?
Answer: IllegalStateException
Streams are single-use.
Stream.of(1, 2, 3).map(n -> n * 10).filter(n -> n > 10).toList() is…
Answer: [20, 30]
Map to 10, 20, 30, then keep those above 10.
What does "lazy" mean for intermediate operations?
Answer: They run only when a terminal operation is called
Nothing happens until the terminal step.
Which operation turns List<Order> into Map<String, List<Order>>?Related
What happens if you remove items from a List<T> inside a foreach over the same list?Related
Answer: InvalidOperationException at run time
The list knows it was changed during enumeration and throws.
Which stream type supports several listeners?Related
What does [3, 1, 2].map((n) => n * 2) return?Related
Pass the quiz (60% or more) or mark this topic as done when you are ready.
Your progress is saved on this device only.
Next steps
- 2 more topics in “Lambdas, streams and files” before its exam: Collectors: grouping and summarising, Reading and writing files.
- Module 8 exam: Lambdas, streams and files · 12 questions · 25 min, without help. 5 topics of this module still to finish first.
- Then the next module, Multithreading and concurrency. 60 topics left in the course before the final exam.