Chapter 11 - Streams Flashcards

1
Q

What are streams in java?

A

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.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

Java Stream Features

A

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.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

Types of operations on streams

A

Intermediate Operations
Terminate Operations

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

Intermadiate Operations

A

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.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

WHat are streams terminal operations

A

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.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

Parallel streams in java

A

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.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

Why Use Parallel Stream?

A

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.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

Explain map() function

A

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.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

Features of map() function

A

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.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

Stream Creation process

A

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.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

Filter() function

A

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.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

features of filter function

A

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.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

Reduce() function

A

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.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

Collect() function

A

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 well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

How collect() Works:

A

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.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

Streams official definition

A

“a sequence of elements from a source
that supports data processing operations.”
Sequence of elements— Like a collection, a stream provides an interface to a sequenced set of values of a specific element type. Because collections are data structures, they’re mostly about storing
and accessing elements with specific time/space complexities (for example, an ArrayList vs. a LinkedList). But streams are about expressing computations such as filter, sorted, and map that
you saw earlier. Collections are about data; streams are about computations. We explain this idea in greater detail in the coming sections.

Source— Streams consume from a data-providing source such as collections, arrays, or I/O resources. Note that generating a stream from an ordered collection preserves the ordering. The elements of a
stream coming from a list will have the same order as the list.

Data processing operations— Streams support database-like operations and common operations from functional programming languages to manipulate data, such as filter, map, reduce, find,
match, sort, and so on. Stream operations can be executed either sequentially or in parallel.

In addition, stream operations have two important characteristics:
Pipelining— Many stream operations return a stream themselves, allowing operations to be chained and form a larger pipeline. This enables certain optimizations that we explain in the next chapter, such as laziness and short-circuiting. A pipeline of operations can be viewed as a database-like query on the data source.

Internal iteration— In contrast to collections, which are iterated explicitly using an iterator, stream operations do the iteration behind the scenes for you.

17
Q

difference between streams and collections

A

Collections:
Imagine you are managing a physical bookstore with shelves and bins filled with various books. These shelves and bins represent a collection of books. Each shelf or bin can hold multiple books, and you can organize them based on genres, authors, or any other criteria that make sense for your store.

In programming, a collection is like a container that holds a group of related objects or data. For example, in Java, you might have an ArrayList to store a collection of books. Collections allow you to store, retrieve, and manipulate groups of items in a structured and organized way.

Streams:
Now, consider a scenario where you have customers coming into the bookstore and browsing through the books. As a customer browses through the shelves, they read the book titles, maybe look at some pages, and eventually make a purchase decision.

In programming, a stream is similar to this browsing experience. It’s a sequence of elements that you can process one by one, like reading through the titles of books on the shelf without physically moving the books. Streams are particularly useful for processing large amounts of data or dealing with data in a continuous or sequential manner.

Difference:
In summary, the main difference is that a collection is a container that holds a group of items (like shelves holding books in a bookstore), allowing easy access to those items, whereas a stream is a sequence of items that you process one by one (like browsing through books on a shelf without physically moving them).

Collections are more about storing and organizing data, making it convenient to access and manipulate them as a group. Streams, on the other hand, are about processing data sequentially or in a streaming fashion, especially when dealing with a potentially large or continuous flow of data.

18
Q

Traversable only once

A

In the context of streams, “traversable only once” refers to the characteristic of streams where the elements can be accessed or consumed in a sequential manner, and once an element is processed or “visited,” it cannot be revisited.

Imagine you have a conveyor belt in a factory where items are moving from one end to the other. Each item represents an element in the stream. As an inspector, you can examine and process each item as it moves past you, but once an item has passed, it’s gone and cannot be re-inspected.

Similarly, in a stream, you can process each element sequentially, performing operations or transformations on them. However, once an element is consumed or processed, it cannot be accessed again from the same stream. If you need to perform multiple operations on the same elements, you would typically create a new stream or reset the stream pointer to its starting position.

19
Q

Does streams use external or internal iteration?

A

Internal

20
Q

Difference between intermadiate and terminal operations

A

Intermediate operations in a Java stream are operations that transform or modify the elements of the stream. However, they do not produce a final result immediately. Instead, they return a new stream that can be further manipulated or acted upon.

Terminal operations in a Java stream are operations that produce a final result or a side effect. Once a terminal operation is invoked, the stream is processed, and the result is obtained.

21
Q

What does in general Working with streams consists

A

To summarize, working with streams in general involves three items:
A data source (such as a collection) to perform a query on
A chain of intermediate operations that form a stream pipeline
A terminal operation that executes the stream pipeline and produces a result

22
Q

Explain Filtering with streams

A

Filtering in Java streams involves selecting specific elements from the stream based on a given predicate or condition. The filter operation is an intermediate operation that allows you to apply a predicate to each element in the stream and include only the elements that match the given condition in the resulting stream.

Here’s a breakdown of how filtering works using the filter operation in a Java stream:

Create a Stream:
First, you need a stream to apply the filtering. You can obtain a stream from a collection, an array, or by using other stream creation methods.

Apply the Filter:
Use the filter intermediate operation to apply a predicate (a boolean-valued function) that defines the condition to filter the elements.

Predicate:
The predicate is a function that takes an element as an argument and returns a boolean indicating whether the element satisfies the condition. If the predicate returns true, the element is included in the filtered stream; otherwise, it is excluded.

Resulting Stream:
The filter operation returns a new stream that includes only the elements for which the predicate returned true.

EXAMPLE:
https://github.com/NavrozashviliDamiane/Java_Streams_Filtering_Example/tree/main/src/main/java/org/filtering

23
Q

Filtering with Distinct

A

In Java, the distinct method is an intermediate operation provided by the Stream API that allows you to obtain a stream containing unique elements, removing any duplicates. It is commonly used when you have a stream of data and you want to operate on the unique elements within that stream.

Here’s a more detailed explanation of the distinct operation:

Removing Duplicates:
The primary purpose of the distinct operation is to eliminate duplicate elements from a stream, leaving only unique elements.

Equality of Elements:
The distinct operation uses the equals method to determine the equality of elements. If two elements are considered equal according to the equals method, only one of them is included in the resulting stream.

Intermediate Operation:
distinct is an intermediate operation, which means it can be followed by other stream operations. It doesn’t produce the final result; rather, it returns a new stream with distinct elements based on the equality defined by the equals method.

Order Preservation:
The distinct operation maintains the order of elements in the original stream. If a stream contains duplicates, the first occurrence of each unique element is preserved, and subsequent duplicates are removed.

EXAMPLE:
https://github.com/NavrozashviliDamiane/Java_Streams_Distinct_Demonstration

24
Q

limit methods in streams

A

Java Stream limit methods are used to restrict the number of elements processed in a stream. These methods include limit(long maxSize) and skip(long n). limit(long maxSize): Use this method to limit the stream to a maximum of maxSize elements. If the stream has fewer elements than maxSize, it remains unchanged.

skip(long n): Use this method to skip the first n elements of a stream and start processing from the n+1-th element.

25
Q

Streams Skip methods

A

The skip method in Java Stream is used to bypass the first n elements of a stream, starting processing from the (n+1)-th element.skip(long n) is useful for skipping a specified number of elements in a stream before processing the rest.

26
Q

Streams mapping in Java

A

Mapping in streams refers to the process of transforming elements of a stream from one type to another or from one state to another using a provided function. It’s a fundamental operation in the Java Stream API, which was introduced in Java 8, and it’s essential for various data manipulation and transformation tasks. In mapping, you apply a given function to each element in a stream and collect the results in a new stream. The transformation can be simple, such as changing the data type, extracting specific properties, or performing more complex operations. The key method used for mapping in Java streams is map

27
Q

Streams map function

A

map function can replace for loop.

The map operation is a method provided by the Stream interface in Java. It takes a Function as a parameter, where the Function defines how each element in the stream should be transformed.

example:
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");</String>

List<String> uppercaseNames = names.stream()
.map(name -> name.toUpperCase())
.collect(Collectors.toList());</String>

System.out.println(uppercaseNames);

28
Q

Streams AllMatch function

A

allMatch: This method checks whether all elements of the stream match the provided predicate. It returns true if all elements satisfy the condition; otherwise, it returns false. For example:

List<Integer> numbers = Arrays.asList(2, 4, 6, 8, 10);</Integer>

boolean allEven = numbers.stream().allMatch(num -> num % 2 == 0);
// Returns true because all numbers are even

29
Q

AnyMatch function in streams

A

anyMatch: This method checks if there is at least one element in the stream that matches the given predicate. It returns true if at least one element satisfies the condition; otherwise, it returns false. For example:

List<String> words = Arrays.asList("apple", "banana", "grape", "orange");</String>

boolean hasLongWord = words.stream().anyMatch(word -> word.length() > 5);
// Returns true because ‘banana’ has more than 5 characters

30
Q

FIndAny method in streams

A

findAny: This method returns an Optional containing any element from the stream. It doesn’t guarantee any specific order and is primarily used in parallel processing or scenarios where you just need some element from the stream without caring which one,

List<String> words = Arrays.asList("apple", "banana", "grape", "orange");</String>

Optional<String> anyWord = words.stream().findAny();
// Returns an Optional containing any element from the stream</String>

31
Q

NoneMatch method in streams

A

noneMatch: This method checks if none of the elements in the stream match the given predicate. It returns true if none of the elements satisfy the condition; otherwise, it returns false. For instance:

List<Integer> numbers = Arrays.asList(1, 3, 5, 7, 9);</Integer>

boolean noneGreaterThanTen = numbers.stream().noneMatch(num -> num > 10);
// Returns true because none of the numbers are greater than 10

32
Q

Reduce Operations in streams

A

The reduce operation in Java’s Stream API allows you to perform computations on the elements of a stream and produce a single result.
examples:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
int result = numbers
.stream()
.reduce(0, (subtotal, element) -> subtotal + element);</Integer>

List<Integer> ages = Arrays.asList(25, 30, 45, 28, 32);
int computedAges = ages.parallelStream().reduce(0, (a, b) -> a + b, Integer::sum);</Integer>

33
Q

Collecting data with streams

A

Collecting data with streams in Java involves using the collect method along with collectors. Collectors provide a way to accumulate elements from a stream into a mutable result container, such as a List, Set, Map, or even a custom data structure.

Here’s an overview of how collecting works with streams:

Basic Collectors:
toList() and toSet():

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> list = numbers.stream().collect(Collectors.toList());
Set<Integer> set = numbers.stream().collect(Collectors.toSet());
These collectors gather elements into a List or Set from the stream.</Integer></Integer></Integer>

toMap():

List<String> countries = Arrays.asList("USA", "Canada", "India", "Australia");
Map<String, Integer> map = countries.stream()
.collect(Collectors.toMap(country -> country, String::length));
This collector transforms elements into a Map where the keys are the elements themselves and the values are their lengths.</String>

Grouping and Partitioning:
groupingBy():

List<String> words = Arrays.asList("apple", "banana", "cherry", "avocado");
Map<Character, List<String>> groupedByFirstChar = words.stream()
.collect(Collectors.groupingBy(s -> s.charAt(0)));
This collector groups elements by a certain criteria—in this case, the first character.</String></String>

partitioningBy():

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Map<Boolean, List<Integer>> evenOddPartition = numbers.stream()
.collect(Collectors.partitioningBy(num -> num % 2 == 0));
This collector partitions elements based on a predicate—in this case, even and odd numbers.</Integer></Integer>