Java Stream API
Java Stream API allows you to process data in a functional style using streams. It provides
a simple way to perform operations like filtering, mapping, and collecting data.
In this chapter, you will learn about the Java Stream API, its features, types of operations
(intermediate, terminal, and short-circuit), methods, and various examples of using
streams.
What is Java Stream API?
Stream API is a feature introduced in Java 8 under the [Link] package that
allows you to process collections of data in a functional way. It does not store elements
but processes them from a source through a pipeline of operations.
Stream provides the following features:
Stream does not store elements. It simply conveys elements from a source such
as a data structure, an array, or an I/O channel through a pipeline of
computational operations.
Stream is functional in nature. Operations performed on a stream do not modify
its source. For example, filtering a stream obtained from a collection produces a
new stream without the filtered elements, rather than removing elements from
the source collection.
Stream is lazy and evaluates code only when required.
The elements of a stream are visited only once during the life of a stream. Like an
Iterator, a new stream must be generated to revisit the same elements of the
source.
We can use streams to filter, collect, print, and convert data from one data structure to
another.
Core Operations on Java Streams
Java Streams support different types of operations that allow you to process and
manipulate data efficiently.
1. Intermediate Operations
Intermediate operations in Java Streams return another Stream. They are typically used
to transform or filter the elements of the original Stream. Since they are lazy, meaning
they do not perform any processing until a terminal operation is called, multiple
intermediate operations can be chained together.
Common Intermediate Operations:
o map(Function<T, R>): Transforms each element of the Stream into another
form using the provided function.
o filter(Predicate<T>): Selects elements from the Stream based on a specified
condition.
o flatMap(Function<T, Stream<R>>): Transforms each element into zero or
more elements by applying a function that returns a stream for each element.
o distinct(): Removes duplicate elements from the Stream.
o sorted(): Sorts the elements of the Stream.
o limit(long n): Truncates the Stream to be no longer than the specified size.
o skip(long n): Skips the first n elements of the Stream.
o peek(Consumer<T>): Performs a specified action on each element of the
Stream without consuming the elements.
import [Link].*;
import [Link];
class Product{
int id;
String name;
float price;
public Product(int id, String name, float price) {
[Link] = id;
[Link] = name;
[Link] = price;
}
}
public class JavaStreamExample {
public static void main(String[] args) {
List<Product> productsList = new ArrayList<Product>();
//Adding Products
[Link](new Product(1,"HP Laptop",25000f));
[Link](new Product(2,"Dell Laptop",30000f));
[Link](new Product(3,"Lenevo Laptop",28000f));
[Link](new Product(4,"Sony Laptop",28000f));
[Link](new Product(5,"Apple Laptop",90000f));
List<Float> productPriceList2 =[Link]()
.filter(p -> [Link] > 30000)// filtering data
.map(p->[Link]) // fetching price
.collect([Link]()); // collecting as list
[Link](productPriceList2);
}
}
Iterating Using Stream
We can use stream to iterate any number of times. Stream provides predefined methods
to deal with the logic we implement. In the following example, we are iterating, filtering
and passed a limit to fix the iteration.
import [Link].*;
public class JavaStreamExample {
public static void main(String[] args){
[Link](1, element->element+1)
.filter(element->element%5==0)
.limit(5)
.forEach([Link]::println);
} }