Advanced Java Unit 3
Advanced Java Unit 3
❑ No Storage: Streams do not store data. They are a view of the data that is consumed
once and cannot be reused.
❑ Laziness: Streams are lazy in the sense that intermediate operations are not executed
until a terminal operation is invoked. This allows for optimization, such as short-circuiting.
❑ Parallel Processing: Streams can be processed in parallel without the need for explicit
multi-threading, making it easier to write parallel code.
Inference:
❖ Streams in Java provide a powerful way to perform data processing operations in a
functional style.
❖ They differ from traditional data structures in their approach to storage, execution, and
parallelism.
❖ Streams do not store data, support lazy evaluation, and offer built-in parallel processing,
making them a versatile tool for modern Java development.
Difference Between Streams and Other Data Structures
Storage
Collections: Collections such as lists, sets, and arrays are data structures that store elements.
Streams : Streams do not store elements. They are used to process elements from a source
Nature of Operations
Collections: Operations on collections are typically performed explicitly using loops and
conditionals.
Streams :Operations on streams are performed using functional-style methods, which are
often more concise and readable.
3. Laziness:
Collections: Operations on collections are eager, meaning they are executed immediately
Streams:: Streams support lazy evaluation, where intermediate operations are not executed until a terminal
operation is invoked.
Generating Streams in Java:
With Java 8, Collection interface has two methods to generate a
Stream.
stream.sort():
• We can sort a stream by calling the sort() method.
• Let’s use the sort() method on the above languages list, as shown in the following code:
languages.stream().sorted().forEach(System.out::println);
• The above method would help sort the elements in alphabetical order.
stream.map():
Stream provides a map() method to map the elements of a stream into another new object. Let’s use the previous example and
convert the elements of the languages list to uppercase, as shown below:
language.stream().map(item->item.uppercase().forEach(System.out::println));
This will map all the elements that are strings in the language collection to their uppercase equivalents.
stream.collect():
Stream API provides a collect() method for processing on the stream interface. When the collect() method is invoked, filtering
and mapping will occur, and the object obtained from those actions will be collected. Let’s take the previous example and obtain
a new list of languages in uppercase, as shown in the below example:
List<String> uase language = languages.stream().map(item>item.toUpperCase()).collect(collectors.toList()));
System.out.println(ucaselanguage);
First, it creates a stream, adds a map to convert the strings to uppercase, and collects all objects in a new list.
limit() method
The purpose of using limit() method is to restrict the size of output to the specified
limit.
skip() method
We can discard the first n elements from the result using skip() method. It takes an
integer as an argument that specifies those elements which will get discarded.
Example
The following example demonstrates how to use skip() method to discard the first
two elements from the filtered result.
TERMINAL OPERATIONS
• Terminal Operations
• Collecting Results(collect)
• Reducing and Summarizing
• (reduce, summaryStatistics)
• Iterating (forEach)
TERMINAL OPERATIONS
• Collecting Results(collect)
• java.util.stream.Collectors class contains static factory methods which
perform some common reduction operations such as accumulating elements
into Collection, finding min, max, average, sum of elements etc.
• All the methods of Collectors class return Collector type which will be supplied
to collect() method as an argument.
• Reducing Reducing and Summarizing
• (reduce, summaryStatistics)
I.e. once you define the condition using a Predicate instance, and provide this Predicate as an
input to the matching methods, then Java 8 processes the matching function internally and
provides you with the result whether a match for the condition was found or not.
Java 8 provides such declarative matching with predicate conditions using three methods
defined on the Streams API which are - allMatch(), anyMatch() and noneMatch().
• anyMatch,
• allMatch
• noneMatch
Stream.allMatch() method
• Stream.allMatch() method returns true if all the elements of the stream match the
provided predicate condition.
• If even one of the elements does not match the predicate condition then the method
skips the testing of the remaining elements using the concept of short-circuit
evaluation and returns false as the result.
• This is a terminal stream operation. Definition of allMatch() Method - The
Stream.allMatch() method has the following signature -
• boolean allMatch(Predicate<? super T> predicate)
• Where,
• - input is predicate which is an instance of a Predicate Functional Interface
• - boolean value is returned indicating whether all elements of the stream match
the predicate or not.
Stream.anyMatch() method
Stream.anyMatch() method returns true if at least 1 of the elements of the stream match the provided predicate
condition.
If none of the elements match the predicate condition then the method returns false.
The moment this method finds the first element satisfying the predicate, it skips the testing of the remaining
elements using the concept of short-circuit evaluation and returns true as the result. This is a terminal stream
operation.
Definition of anyMatch() Method - The Stream.anyMatch() method has the following signature -
boolean anyMatch(Predicate<? super T> predicate)
Where,
- input is predicate which is an instance of a Predicate Functional Interface
- boolean value is returned indicating whether any of the elements of the stream match the
predicate or not.