Enrol to start learning
Reading is open to everyone. Enrolling is free, and it is what unlocks the audio lessons, practice tests and progress tracking.
5.4. Stream Operations
Interactive Audio Lesson
Unlock the classroom podcast
The transcript is above and free to read. A free account plays the conversation back.
Create a free accountToday, let's explore intermediate operations in Java Streams. Who can tell me what intermediate operations do?
Are they operations that modify the elements in a Stream but still return a Stream?
Exactly! They allow data transformation without affecting the original Stream. Can anyone name some intermediate operations?
There's filter, map, and sorted!
Great! Remember, these operations create a new Stream. One way to remember this is the acronym 'FMS' - for Filter, Map, Sorted. Let’s discuss filter first.
How does filter work?
The 'filter' method takes a predicate and returns elements that satisfy the condition. For example, if we have a list of names, we can filter those that start with a certain letter. What about mapping?
Does map change the data type of elements?
Exactly! It transforms each element. Think about it as converting apples to apple pies! Let's wrap up this session. We talked about intermediate operations, specifically the filter and map methods, and how they empower our data processing.
Unlock the classroom podcast
The transcript is above and free to read. A free account plays the conversation back.
Create a free accountNow, let’s shift our focus to terminal operations. Who can explain what terminal operations do?
They perform an action and end the Stream processing, right?
Exactly! Terminal operations yield a result but also consume the Stream. Can anyone mention a few examples?
ForEach, collect, and reduce?
Correct! 'ForEach' executes an action for each element, while 'collect' gathers elements into a collection. Let’s talk a bit about reduce.
How does reduce work?
The 'reduce' method combines elements into a single result. For instance, you can sum up a list of integers. Remember, with terminal operations, the stream is consumed. An easy way to recall their nature is to think of the saying, 'Terminal tasks end the game.' Let’s summarize what we discussed.
Unlock the classroom podcast
The transcript is above and free to read. A free account plays the conversation back.
Create a free accountCan anyone explain how we can combine intermediate and terminal operations?
I think we take a Stream and perform some transformations before concluding with a terminal operation?
Precisely! Let’s consider an example. If we have a list of names, we might want to filter names starting with 'C', convert them to uppercase, and then print them out. How would that look in code?
"It could be:
Overview
Short Summary
This section introduces the two categories of operations on Java Streams: intermediate and terminal operations.
Medium Summary
Stream operations in Java are categorized into intermediate operations, which return a Stream, and terminal operations, which produce a result or a side-effect. Key operations include filtering, mapping, and reducing data within a stream.
Detailed Summary
Stream Operations in Java
In Java Streams, operations are primarily classified into two types: intermediate operations and terminal operations. Understanding these operations is crucial for efficiently processing data using streams.
Intermediate Operations
These operations are designed to transform or filter data and always return a new Stream. Key intermediate operations include:
- filter(predicate): Filters elements based on a provided condition, returning only those that match.
- map(function): Transforms each element of the Stream into another form, using a given function.
- sorted(): Sorts the elements of the Stream in natural order or according to a provided comparator.
- distinct(): Eliminates duplicate elements in the Stream.
- limit(n): Limits the number of elements returned to the first n elements.
Terminal Operations
Terminal operations perform an action on the Stream and yield a result or side-effect, consuming the Stream in the process. Examples of terminal operations are:
- forEach(consumer): Applies a given action to each element in the Stream.
- collect(): Accumulates elements into a collection or in a summarized format.
- reduce(identity, accumulator): Combines elements into a single value based on the specified operation (e.g., sum).
- count(): Counts the number of elements in the Stream.
- anyMatch(predicate), allMatch(predicate), noneMatch(predicate): Check for matches in the Stream based on the provided condition.
These operations allow developers to utilize a clear and declarative way of coding data manipulation tasks. For example, to filter names that start with 'C', transform them to uppercase, and print them, one can use:
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");
names.stream()
.filter(n -> n.startsWith("C"))
.map(String::toUpperCase)
.forEach(System.out::println);In this example, the order of operations and functional style enhances readability and maintains the immutability of the original data.
Reference YouTube Videos
Audio Book
Unlock the audio lesson
The script is above and free to read. A free account plays it back, in the voice you pick.
Create a free accountStream operations are of two types:
-
Intermediate Operations (return a stream):
• filter(): Filters elements based on a condition. • map(): Transforms elements. • sorted(): Sorts elements. • distinct(): Removes duplicates. • limit(n): Limits output to n elements.
-
Terminal Operations (produce a result or side-effect):
• forEach(): Performs an action for each element. • collect(): Converts the stream into a collection or result. • reduce(): Reduces stream to a single value. • count(): Counts elements. • anyMatch(), allMatch(), noneMatch(): Matching operations.
Detailed Explanation
Stream operations in Java are divided into two main categories: Intermediate Operations and Terminal Operations.
-
Intermediate Operations are operations that return a new stream. This means they can be chained together to form a query. Examples include:
- filter(): Selects elements from a stream based on a specified condition. For example, filtering a list to include only names that start with 'A'.
- map(): Transforms each element in the stream. For instance, converting all names to uppercase.
- sorted(): Orders the elements in natural order or by a specified comparator.
- distinct(): Removes duplicate elements from the stream.
- limit(n): Restricts the output to the first 'n' elements.
-
Terminal Operations, on the other hand, produce a result or a side effect. They do not return a stream. Examples include:
- forEach(): Executes a given action for each element in the stream.
- collect(): Gathers the elements from the stream into a collection.
- reduce(): Combines elements in the stream into a single value through a specified binary operation (e.g., sum).
- count(): Counts the number of elements in the stream.
- anyMatch(), allMatch(), noneMatch(): Used for checking conditions on the stream elements.
Examples & Analogies
Imagine you are organizing a group of friends for a movie night. You first create a list of friends (the stream).
- You might use filter() to create a subset of friends who said they are available.
- Then, you can use map() to transform their names to uppercase when sending out the invitations for fun.
- If you find duplicates in your invite list, you can apply distinct() to ensure everyone gets invited just once.
- Finally, you might use forEach() to send the invitation to each friend about the movie night.
In this analogy, your list of friends correspond to a stream, and the various operations correspond to the stream operations you can perform to manipulate the list and notify them.
Unlock the audio lesson
The script is above and free to read. A free account plays it back, in the voice you pick.
Create a free accountExample:
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");
names.stream()
.filter(n -> n.startsWith("C"))
.map(String::toUpperCase)
.forEach(System.out::println);Detailed Explanation
This example illustrates the usage of stream operations in Java.
- First, a list containing names is created using
Arrays.asList(). - The stream() method is called on the list, which creates a stream from it.
- filter() is then applied to the stream to keep only those names that start with 'C'. The lambda expression
n -> n.startsWith("C")serves as the condition for filtering. - Next, map() is used to convert the remaining names to uppercase. Using
String::toUpperCaseis a method reference that makes the code cleaner. - Finally, forEach() prints each name to the console. This operation goes over all of the names in the stream and prints them out, effectively giving us the uppercase version of 'Charlie'. Overall, this demonstrates a typical use case of stream operations: establishing a pipeline where data flows through several transformations.
Examples & Analogies
Think of the above example as a process of sorting through book titles. You have a list of titles: 'Alice in Wonderland', 'Bob the Builder', 'Charlie and the Chocolate Factory', and 'David Copperfield'.
- First, you decide to only keep the titles that start with 'C'—like filtering out books you’re not interested in.
- Then, you want to highlight the favorite title, so you transform 'Charlie and the Chocolate Factory' to make it stand out in uppercase.
- Finally, you share the selected title with your friends. In this scenario, each of the stream operations corresponds to the steps you took to narrow down and highlight your favorite book title.
--
Key Concepts
Core takeaways and short definitions to help you quickly recall the key ideas from this section.
Intermediate Operations: Operations that return a Stream, allowing for transformations.
Terminal Operations: Operations that produce a result and consume the Stream.
filter(): Used to filter elements in a Stream based on a condition.
map(): Transforms data within the Stream.
forEach(): Executes an action on each element of the Stream.
collect(): Gathers Stream elements into a collection.
Examples
Memory Aids
Interactive tools to help you remember key concepts
Stories
Flash Cards
Glossary
Intermediate Operations
Operations that transform or filter data in a Stream and return a new Stream.
Terminal Operations
Operations that consume the Stream and produce a result or side-effect.
filter()
An intermediate operation that returns a Stream consisting of the elements that match a given predicate.
map()
An intermediate operation that applies a function to each element of the Stream, transforming it.
forEach()
A terminal operation that executes a given action for each element in the Stream.
collect()
A terminal operation that transforms the Stream into a different form, usually a collection.
reduce()
A terminal operation that combines the elements of the Stream into a single result.
count()
A terminal operation that counts the number of elements in the Stream.