Chapter 11 - Streams Flashcards
What are streams in java?
Streams in Java are a powerful and flexible way to process collections of data in a functional and declarative manner. Introduced in Java 8 as part of the Stream API, they allow for concise and expressive operations on sequences of elements. A stream is not a data structure itself but rather a way to process and operate on data from a source, such as a collection, array, or input/output channel.
Java Stream Features
A stream is not a data structure instead it takes input from the Collections, Arrays or I/O channels.
Streams don’t change the original data structure, they only provide the result as per the pipelined methods.
Each intermediate operation is lazily executed and returns a stream as a result, hence various intermediate operations can be pipelined. Terminal operations mark the end of the stream and return the result.
Types of operations on streams
Intermediate Operations
Terminate Operations
Intermadiate Operations
Intermediate Operations are the types of operations in which multiple methods are chained in a row.
Characteristics of Intermediate Operations
Methods are chained together.
Intermediate operations transform a stream into another stream.
It enables the concept of filtering where one method filters data and passes it to another method after processing.
some of those operations are: map(), filter(), sorted()
Intermediate operations such as filter or sorted return another stream as the return type. This
allows the operations to be connected to form a query. What’s important is that intermediate
operations don’t perform any processing until a terminal operation is invoked on the stream
pipeline—they’re lazy. This is because intermediate operations can usually be merged and
processed into a single pass by the terminal operation.
WHat are streams terminal operations
Terminal Operations are the type of Operations that return the result. These Operations are not processed further just return a final result value. for ex: collect(), forEach(), reduce().
Terminal operations produce a result from a stream pipeline. A result is any nonstream value
such as a List, an Integer, or even void.
Parallel streams in java
Normally any java code has one stream of processing, where it is executed sequentially. Whereas by using parallel streams, we can divide the code into multiple streams that are executed in parallel on separate cores and the final result is the combination of the individual outcomes. The order of execution, however, is not under our control.
Therefore, it is advisable to use parallel streams in cases where no matter what is the order of execution, the result is unaffected and the state of one element does not affect the other as well as the source of the data also remains unaffected.
Why Use Parallel Stream?
In a scenario where we have a large number of books (1,000,000 in this example), using a parallel stream can take advantage of multiple CPU cores and divide the workload, potentially leading to faster processing.
When calculating the total price using a parallel stream, the workload is distributed across multiple threads, each working on a portion of the book list. This parallelism can significantly speed up the summing operation, especially when the dataset is large.
Explain map() function
map() operation is a intermediate operation that transforms each element of the stream using a provided function. It applies the function to each element in the stream, producing a new stream of the transformed elements. This allows you to perform a one-to-one mapping of elements from the input stream to elements in the output stream.
Features of map() function
Element Transformation: The map() function transforms each element in the stream based on the provided mapping function.
One-to-One Mapping: It performs a one-to-one mapping, meaning each input element is transformed into exactly one output element.
Type Transformation: You can change the type of elements in the stream by specifying a different return type in the mapping function.
Intermediate Operation: map() is an intermediate operation, meaning it doesn’t produce a final result but returns a new stream that can be further processed.
Functional Interface Usage: It leverages the java.util.function.Function interface to define the mapping function.
Method Reference: You can use method references to specify the mapping function, making the code concise.
Lazy Evaluation: The mapping function is applied lazily and only when the terminal operation is called, allowing for efficient computation.
Immutability: The original elements in the stream are not modified; instead, a new stream with transformed elements is created.
Stream Creation process
When you create a stream from a collection, an array, or other sources, a stream object is instantiated. This object is responsible for managing the elements and facilitating the stream operations.
Filter() function
filter function is an intermediate operation that allows you to select and process elements from the stream based on a specified predicate. The predicate is a boolean-valued function that determines whether an element should be included in the resulting stream.
features of filter function
Element Selection:
The primary purpose of the filter() function is to select elements from the stream based on a specified predicate.
Predicate Parameter:
It takes a predicate (a functional interface) as a parameter, which is a boolean-valued function. This function determines whether an element should be included in the resulting stream.
Condition-Based Filtering:
The predicate evaluates a condition for each element in the stream. Elements that satisfy the condition (predicate returns true) are included in the new stream; others are excluded.
Reduce() function
reduce() function is a terminal operation that performs a reduction on the elements of the stream based on an associative accumulation function and returns an Optional.
Collect() function
collect() function is a terminal operation that transforms the elements of the stream into a different form, usually a collection like a List, Set, or Map, or even a single value. It’s a flexible and powerful way to gather the elements of a stream into a specific type of result.
How collect() Works:
Supplier Initialization:
The supplier is invoked to create an initial accumulation container.
Accumulation:
The accumulator function is applied to each element in the stream, updating the accumulation container accordingly.
Combining Accumulators (in Parallel):
If the stream is processed in parallel, accumulations from different parts of the stream are combined using the combiner function.
Final Transformation:
If a finisher function is provided, it’s applied to the accumulation container to produce the final result.
Terminal Operation:
The collect() function is a terminal operation that triggers the accumulation process and returns the final result.