0% found this document useful (0 votes)
19 views14 pages

UNIT 5 CLASS NOTES

fbsbdfb fdbfd

Uploaded by

jothishwar007
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
19 views14 pages

UNIT 5 CLASS NOTES

fbsbdfb fdbfd

Uploaded by

jothishwar007
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 14

UNIT 5

ADVANCED STREAM FEATURES


AND
REGULAR EXPRESSIONS
Importance and Use Cases of Advanced Stream Features
• Efficiency and Performance: Streams allow for efficient data processing by
enabling operations like filtering, mapping, and reducing without the need for
explicit loops.
• Parallel Processing: Streams support parallel execution, which can
significantly improve performance for large datasets by leveraging multi-core
processors.
• Functional Programming
: Streams promote a functional programming style, which can lead to more
predictable and maintainable code by avoiding mutable state and side effects
• Expressiveness:
The Stream API provides a rich set of operations that can be combined in a fl
uent manner,
making the code more expressive and easier to understand
Use Cases of Advanced Stream Features

• Data Transformation: Streams can be used to


transform data from one form to another. For example,
converting a list of stings to uppercase:

List<String> upperCaseNames = names.stream()

.map(String::toUpperCase)

.collect(Collectors.toList());
• Filtering Data: Streams make it easy to filter data based on certain criteria.
For instance, filtering out even numbers from a list:

List<Integer> oddNumbers = numbers.stream()

.filter(n -> n % 2 != 0)

.collect(Collectors.toList());

• Aggregation Operations: Streams support aggregation operations like


sum, average, and count. For example, calculating the sum of a list of
integers:

int sum = numbers.stream()

.mapToInt(Integer::intValue)

.sum();
• Parallel Processing: Streams can be processed in parallel to improve
performance. For example, summing a large list of integers in parallel:

int parallelSum = numbers.parallelStream()

.mapToInt(Integer::intValue)

.sum();

• Complex Data Pipelines: Streams can be used to create complex data processing
pipelines. For example, filtering, mapping, and collecting data in a single pipeline:

List<String> result = data.stream()

.filter(d -> d.startsWith("A"))

.map(String::toLowerCase)

.collect(Collectors.toList());
Java's stream API
• Simplified Data Processing

Importance: Advanced stream features simplify complex data processing tasks, making the code more readable and
maintainable by abstracting away the boilerplate code.

Use Cases:

Data Transformation: Converting a list of objects into another form, such as mapping user entities to DTOs (Data
Transfer Objects).

Filtering Data: Easily filtering large datasets based on specific criteria, such as finding all active users or filtering
transactions above a certain threshold.

• Parallel Processing

Importance: Streams can be processed in parallel to leverage multi-core processors, which improves performance
when dealing with large data sets.

Use Cases:

Batch Processing: Handling large batches of data, such as processing millions of records in a database.

Big Data: Performing complex computations over large datasets, like summing up values or aggregating
statistics.
• Functional Programming Integration
Importance: Streams provide a functional programming approach to data processing,
which allows for more expressive and concise code.
Use Cases: Event Handling: Using streams in event-driven systems to handle and
process events functionally.
Custom Collectors: Creating custom collectors for complex data aggregations, such as
grouping and partitioning data.
• Enhanced Debugging and Testing
Importance: Advanced stream features, such as peek and custom collectors, help in
debugging and testing stream operations by providing intermediate operation insights.
Use Cases: Logging: Using peek() to log stream elements as they are processed, which
aids in debugging complex streams.
Testable Pipelines: Breaking down stream operations into smaller, testable units,
making it easier to verify the correctness of each stage.
• Stream Customization and Extension
Importance: Java allows customization and extension of stream
behavior through custom collectors, spliterators, and more, which
increases the flexibility of the stream API.
• Use Cases:
Custom Collectors: Implementing custom collectors for specific
aggregation needs, such as collecting statistics with custom rules.
Spliterators: Creating custom spliterators for non-standard data
sources, like iterating over data structures that aren't inherently
sequential.
Creating Custom Streams
Creating custom streams in Java involves defining a stream from
non-standard data sources or operations that are not directly
supported by the standard Stream API.

This process typically involves the use of

• Spliterator

• Stream.Builder

• Stream.generate methods.
Steps to Create Custom Streams in Java

1. Using Stream.of() and Stream.Builder()

Stream.of(): Creates a stream from a specified set of


elements.

Stream.Builder: Useful when you need to build a stream step


by step.

Stream<String> stream = Stream.of("apple", "banana",


"cherry");

Stream<String> builtStream =
2. Using Stream.generate()

Stream.generate(): Creates an infinite stream where each element


is generated using a Supplier function.

Stream<Double>randomNumbers=Stream.generate(Math::random).li
mit(10);

3. Using Stream.iterate()

Stream.iterate(): Creates an infinite stream where each element is


produced by applying a function to the previous element.

Stream<Integer> evenNumbers = Stream.iterate(0, n -> n +


2).limit(10);
4. Creating Streams from Custom@Override
Data Structures public boolean
class CustomSpliterator implementstryAdvance(Consumer<? super
Spliterator<Integer> { Integer> action) {

private final int[] array; if (index < array.length) {

private int index = 0; action.accept(array[index++]);

public CustomSpliterator(int[] array) return true;


{ }
this.array = array; return false;
} }
@Override @Override
public Spliterator<Integer> trySplit() { public int characteristics() {
int length = array.length - index; return SIZED | SUBSIZED | ORDERED;
if (length <= 1) return null; }
int splitIndex = length / 2 + index; }
Spliterator<Integer> spliterator = new public class CustomStream {
CustomSpliterator(Arrays.copyOfRange(array, public static void main(String[] args) {
index, splitIndex)); int[] array = {1, 2, 3, 4, 5};
index = splitIndex; Spliterator<Integer> spliterator = new
return spliterator; CustomSpliterator(array);
} Stream<Integer> stream =
@Override StreamSupport.stream(spliterator, false);
public long estimateSize() { stream.forEach(System.out::println);
• }

return array.length - index; • }

}
INFINITE STREAMS

You might also like