Java 8 Stream API: Functional Programming Made Easy
Beginner's Guide to Java Stream API
Getting Started
In Java, a stream is a sequence of elements that supports
various operations to perform computations upon its elements. It is not a data
structure itself. The Stream API was introduced in Java 8 to facilitate
functional-style operations on streams of elements, such as collections (like
lists and sets) or other sources. It allows developers to express common manipulations
(like filtering, mapping, sorting, etc.) on these collections concisely and
efficiently.
Creating
Streams
Streams
can be created from various sources including:
Collections
Use stream()
method from collections like List, Set, Map, etc.
List<Integer>
numbers = Arrays.asList(10, 20, 30, 40, 50);
Stream<Integer>
stream = numbers.stream();
Arrays
Use Arrays.stream() for arrays of
primitive types or Stream.of() for arrays of objects
int[]
array = {1, 2, 3, 4, 5};
IntStream
stream = Arrays.stream(array);
Static Factory Methods
Stream interface provides static
factory methods like Stream.of(), Stream.iterate(), Stream.generate(),
etc.,
Stream<String>
stringStream = Stream.of("a", "b", "c");
Data Processing with Collections
01.EXAMPLE 👇
This example demonstrates the basic usage of streams in Java for processing and iterating over elements in a collection.
Explanation:
List Initialization:
List<Integer> nums =
Arrays.asList(20, 10, 50, 30, 40);
This
line creates a List of integers nums containing the elements [20, 10, 50, 30,
40]
using
Arrays.asList().
Creating
a Stream:
Stream<Integer> data = nums.stream();
stream()
is a method available on the Collection interface (and its implementations like
List). It converts the collection (nums in this case) into a sequential stream
of elements (Integer in this case).
Processing the Stream:
data.forEach(n ->
System.out.println(n));
forEach()
is a terminal operation that iterates over each element of the stream and
applies the provided function (n -> System.out.println(n)) to each element.
In
this case, the lambda expression n -> System.out.println(n) prints each
element (n) of the stream to the console.
Explanation:
List Initialization:
List<Integer> nums =
Arrays.asList(20, 10, 50, 30, 40);
Creates
a list nums containing integers [20, 10, 50, 30, 40] using Arrays.asList().
Creating
a Stream:
Stream<Integer> data = nums.stream();
Converts
the list nums into a stream data of type Stream<Integer> using the
stream() method provided by the List interface.
Processing the
Stream:
data.forEach(n -> System.out.println(n));
Uses
the forEach() method to iterate over each element (n) in the stream and print
it to the console. This is a terminal operation that consumes the elements of
the stream.
Trying to Reuse
the Stream:
data.forEach(n -> System.out.println(n));
Attempts
to reuse the same stream data again to iterate and print its elements.
Issue:
In Java streams, once a terminal operation (like forEach) is called on a stream, the stream is considered consumed and cannot be reused. This results in an IllegalStateException with the message "stream has already been operated upon or closed".
03.EXAMPLE👇
Explanation:
Imports:
java.util.Arrays: Provides utility
methods for arrays, including asList used here.
java.util.List: Represents an ordered collection
(list).
java.util.function.Consumer: Represents
an operation that accepts a single input argument and returns no result.
java.util.stream.Stream: Represents a
sequence of elements supporting sequential and parallel aggregate operations.
Class Declaration:
Defines a public class named
DoubleTheDataUsingStream.
Main Method (public static void
main(String[] args))
This is the entry
point of the Java program.
List
Initialization:
List<Integer> nums = Arrays.asList(20,
10, 50, 30, 40);
Creates a list
named nums containing integers 20, 10, 50, 30, 40.
Stream
Creation:
Stream<Integer> data = nums.stream();
Converts the nums
list into a stream of integers (Stream<Integer>).
Stream Mapping:
Stream<Integer> mappedData =
data.map(n -> n * 2);
Applies a
transformation to each element in the data stream by doubling each integer (n *
2). This creates a new stream (mappedData) where each element is twice the
corresponding element in data.
Stream
Terminal Operation (forEach):
mappedData.forEach(n ->
System.out.println(n));
Performs an
action for each element of the mappedData stream. Here, it prints each element
to the console.
Execution Flow:
The list nums is
converted into a stream (data).
Each element in
data is then mapped to its double value (mappedData).
Finally, each doubled value in mappedData is printed to the consol
04.EXAMPLE👇
Explanation:
Imports:
java.io.LineNumberInputStream: This
import is not used in the code and can be removed without affecting the functionality.
Class Declaration:
public class DoubledTheValue: Defines a
public class named DoubledTheValue.
Main Method (public static void
main(String[] args)):This is the entry point of the Java program.
List Initialization:
List<Integer> nums = Arrays.asList(20,
10, 50, 30, 40);
Creates a list
named nums containing integers 20, 10, 50, 30, 40.
Enhanced For-loop (for (int n : nums)):
Iterates over each
element (n) in the nums list.
Calculation and Output:
System.out.println(n * 2);
For each integer n
in the list, multiplies it by 2 (n * 2) and prints the result to the console.
Explanation:
Imports:
java.io.LineNumberInputStream: This
import statement is not used in the code and can be safely removed.
Class Declaration:
public class DoubleTheValueUsingBuilderPattern: Defines a public
class named DoubleTheValueUsingBuilderPattern.
Main Method (public static void main(String[] args)):
This is the entry
point of the Java program.
List Initialization:
List<Integer> nums = Arrays.asList(20,
10, 50, 30, 40);
Creates a list
named nums containing integers 20, 10, 50, 30, 40.
Stream Processing:
nums.stream(): Converts the nums list into a stream of integers.
.map(n -> n * 2): Applies
a mapping function to each number in the stream to double its value (n * 2).
.forEach(n -> System.out.println(n)): Iterates over each element in the stream and prints it to the console.
Explanation:
Imports:
java.io.LineNumberInputStream: This
import statement is not used in the code and can be safely removed.
Class Declaration:
public class SortedDataList: Defines a public class named
SortedDataList.
Main Method (public static void main(String[] args)):
This is the entry
point of the Java program.
List Initialization:
List<Integer> nums = Arrays.asList(20, 10, 50, 30, 40);
Creates a list named nums
containing integers 20, 10, 50, 30, 40.
Stream Creation:
Stream<Integer> data = nums.stream();
Converts the nums list into a
stream of integers (Stream<Integer>).
Sorting:
Stream<Integer> sortedData = data.sorted();
Sorts the elements in the stream
data. By default, it sorts in natural order (ascending).
Terminal Operation (forEach):
sortedData.forEach(n -> System.out.println(n));
Iterates over each element in the sorted.Data stream and prints it to the console.
Explanation:
java.io.LineNumberInputStream: This import statement is not used in the code and can be safely removed.
Class Declaration:
public class Filter_Sort_MapTheValue:
Defines a public class named Filter_Sort_MapTheValue.
Main Method (public static void main(String[] args)):This
is the entry point of the Java program.
List Initialization:
List<Integer> nums =
Arrays.asList(20, 11, 50, 30, 43);
Creates a list
named nums containing integers 20, 11, 50, 30, 43.
Stream Creation:
nums.stream(): Converts the nums list
into a stream of integers.
Stream Operations:
.filter(n -> n % 2 == 1): Filters
the stream to include only odd numbers (n % 2 == 1).
.sorted(): Sorts the filtered numbers
in ascending order (natural order).
.map(n -> n * 2): Applies a mapping
function to each number in the stream to double its value (n * 2).
.forEach(n -> System.out.println(n)): Iterates over each element in the stream and prints it to the console.
08.EXAMPLE👇
Explanation:
Imports:
java.io.LineNumberInputStream: This
import is not used in the code and can be removed.
Class Declaration:
public class PredicateFunction: Defines
a public class named PredicateFunction.
Main Method (public static void main(String[] args)):
This is the entry
point of the Java program.
List Initialization:
List<Integer> nums =
Arrays.asList(20, 11, 50, 30, 43);
Creates a list
named nums containing integers 20, 11, 50, 30, 43.
Predicate Definition:
Predicate<Integer> predi = new
Predicate<Integer>() { ... };
Defines a
predicate named predi that checks if a given integer is odd (n % 2 == 1). This
is implemented using an anonymous inner class that overrides the test method of
the Predicate interface.
Stream Processing:
nums.stream(): Converts the nums list
into a stream of integers.
.filter(predi): Filters the stream to
include only numbers that satisfy the predicate predi (i.e., odd numbers).
.sorted(): Sorts the filtered numbers
in ascending order (natural order).
.map(n -> n * 2): Applies a mapping
function to each number in the stream to double its value.
.forEach(n -> System.out.println(n)): Iterates over each element in the stream and prints it to the console.
09.EXAMPLE👇
Explanation:
Imports:
java.io.LineNumberInputStream: This
import is not used in the code and can be removed.
Class Declaration:
public class PredicateFunctionShort2:
Defines a public class named PredicateFunctionShort2.
Main Method (public static void main(String[] args)):
This is the entry
point of the Java program.
List Initialization:
List<Integer> nums =
Arrays.asList(20, 11, 50, 30, 43);
Creates a list
named nums containing integers 20, 11, 50, 30, 43.
Predicate Definition Using
Lambda Expression:
Predicate<Integer> predi = n -> n
% 2 == 1;
Defines a
predicate named predi using a lambda expression. The lambda expression checks
if a given integer n is odd (n % 2 == 1).
Stream Processing:
nums.stream(): Converts the nums list into a stream of integers.
.filter(predi): Filters the stream to
include only numbers that satisfy the predicate predi (i.e., odd numbers).
.sorted(): Sorts the filtered numbers
in ascending order (natural order).
.map(n -> n * 2): Applies a mapping
function to each number in the stream to double its value.
.forEach(n -> System.out.println(n)): Iterates over each element in the stream and prints it to the console.
10.EXAMPLE👇
Explanation:
Imports:
java.io.LineNumberInputStream: This
import is not used in the code and can be removed.
Class Declaration:
public class PredicateFunctionShort1:
Defines a public class named PredicateFunctionShort1.
Main Method (public static void main(String[] args)):
This is the entry
point of the Java program.
List Initialization:
List<Integer> nums =
Arrays.asList(20, 11, 50, 30, 43);
Creates a list
named nums containing integers 20, 11, 50, 30, 43.
Predicate Definition:
Predicate<Integer> predi = new
Predicate<Integer>() { ... };
Defines a
predicate named predi that checks if a given integer is odd (n % 2 == 1). This
is implemented using an anonymous inner class that overrides the test method of
the Predicate interface.
Stream Processing:
nums.stream(): Converts the nums list
into a stream of integers.
.filter(predi): Filters the stream to
include only numbers that satisfy the predicate predi (i.e., odd numbers).
.sorted(): Sorts the filtered numbers
in ascending order (natural order).
.map(n -> n * 2): Applies a mapping
function to each number in the stream to double its value.
.forEach(n -> System.out.println(n)):
Iterates over each element in the stream and prints it to the console.
11.EXAMPLE👇
Explanation:
Imports:
java.io.LineNumberInputStream: This
import is not used in the code and can be removed.
Class Declaration:
public class PredicateFunctionShort2:
Defines a public class named PredicateFunctionShort2.
Main Method (public static void main(String[] args)):
This is the entry
point of the Java program.
List Initialization:
List<Integer> nums =
Arrays.asList(20, 11, 50, 30, 43);
Creates a list
named nums containing integers 20, 11, 50, 30, 43.
Predicate Definition Using
Lambda Expression:
Predicate<Integer> predi = n -> n
% 2 == 1;
Defines a
predicate named predi using a lambda expression. The lambda expression checks
if a given integer n is odd (n % 2 == 1).
Stream Processing:
nums.stream(): Converts the nums list
into a stream of integers.
.filter(predi): Filters the stream to
include only numbers that satisfy the predicate predi (i.e., odd numbers).
.sorted(): Sorts the filtered numbers
in ascending order (natural order).
.map(n -> n * 2): Applies a mapping
function to each number in the stream to double its value.
.forEach(n -> System.out.println(n)): Iterates over each element in the stream and prints it to the console.
12.EXAMPLE👇
Explanation:
Imports:
java.io.LineNumberInputStream: This import statement is not used in the code and can be safely removed.
Class Declaration:
public class PredicateFunctionShortestCode: Defines a public class
named PredicateFunctionShortestCode.
Main Method (public static void main(String[] args)):
This is the entry
point of the Java program.
List Initialization:
List<Integer> nums =
Arrays.asList(20, 11, 50, 30, 43);
Creates a list
named nums containing integers 20, 11, 50, 30, 43.
Stream Creation:
nums.stream(): Converts the nums list
into a stream of integers.
Stream Operations:
.filter(n -> n % 2 == 1): Filters
the stream to include only odd numbers (n % 2 == 1).
.sorted(): Sorts the filtered numbers
in ascending order (natural order).
.map(n -> n * 2): Applies a mapping
function to each number in the stream to double its value (n * 2).
.forEach(n -> System.out.println(n)): Iterates over each element in the stream and prints it to the console.
12.EXAMPLE👇
Explanation:
Imports:
java.io.LineNumberInputStream: This
import statement is not used in the code and can be safely removed.
Class Declaration:
public class AddingValueInTheList:
Defines a public class named AddingValueInTheList.
Main Method (public static void main(String[] args)):
This is the entry
point of the Java program.
List Initialization:
List<Integer> nums =
Arrays.asList(20, 11, 50, 30, 43);
Creates a list
named nums containing integers 20, 11, 50, 30, 43.
Stream Creation:
nums.stream(): Converts the nums list
into a stream of integers.
Stream Operations:
.filter(n -> n % 2 == 1): Filters
the stream to include only odd numbers (n % 2 == 1).
.sorted(): Sorts the filtered numbers
in ascending order (natural order).
.map(n -> n * 2): Applies a mapping
function to each number in the stream to double its value (n * 2).
.reduce(0, (CarriedValue, NewValue) ->
CarriedValue + NewValue): Reduces the stream to a single value by summing
all elements, starting with an initial value of 0.
Result Assignment and Output:
int result = ...: Stores the result of
the stream operations (sum of doubled odd numbers).
System.out.println(result);: Prints the
computed sum to the console.
Key Characteristics of Streams
Sequence of Elements:
A stream provides a way to convey elements from a source, one at a time,
through a sequence of operations.
Aggregate Operations:
Streams support aggregate operations like filtering, mapping, sorting, and
reducing elements. These operations can be chained together to form a pipeline.
Lazy Evaluation:
Intermediate operations on a stream are lazily evaluated. This means that
intermediate operations do not start processing elements until a terminal
operation is invoked. Lazy evaluation allows streams to optimize performance by
avoiding unnecessary computations.
Immutability:
Streams do not modify the underlying data source. Instead, they provide an
interface to perform operations on the data in a non-destructive manner.
Comments
Post a Comment