Streams in Java- Complete Tutorial with Examples

Learn via video course
FREE
View all courses
Java Course - Mastering the Fundamentals
Java Course - Mastering the Fundamentals
by Tarun Luthra
1000
5
Start Learning
Java Course - Mastering the Fundamentals
Java Course - Mastering the Fundamentals
by Tarun Luthra
1000
5
Start Learning
Topics Covered

Streams in Java, a feature introduced in Java 8, revolutionized data processing by offering a functional and declarative approach. They enable developers to perform sequential or parallel aggregate operations on sequences of objects efficiently.

The Stream API in Java provides a collection of stream classes that facilitate the manipulation and transformation of data. These streams allow developers to write expressive and concise code while maintaining high efficiency.

Understanding streams in Java is paramount for modern Java developers. They empower developers to write code that is efficient and easy to read and maintain. By leveraging streams, developers can efficiently perform complex data processing tasks, leading to cleaner and more maintainable codebases.

See Also: Complete Java Tutorial

Java Stream Features

Functional-style operations: Streams support functional-style operations like map, filter, and reduce, which enable developers to express data processing logic in a more declarative and readable way.

Pipelining: Streams enable the seamless chaining of operations into a pipeline, where the result of each operation feeds directly into the next. This enables efficient and compact code without the need for intermediate collections.

Lazy evaluation: Streams employ lazy evaluation, meaning intermediate operations are only executed once a terminal operation is invoked. This improves efficiency by avoiding unnecessary computation.

Parallel processing: Streams can be processed in parallel, leveraging multi-core architectures to improve performance for large datasets. Parallel streams automatically divide the data into multiple chunks and process them concurrently.

Streams in Java provide a powerful and efficient way to process data by applying various sequential and parallel aggregate operations. The Stream API in Java 8 introduced the concept of streams and stream classes in Java, which offer specialized functionality for manipulating and transforming data. Developers can utilize the Stream API in Java to write more concise, expressive, and efficient code.

The Stream API in Java provides a rich set of operations that can be applied to streams, such as filtering, mapping, and reducing. The Stream API in Java provides a high-level abstraction for working with streams and offers a wide range of operations to manipulate and process data.

Introduction of Streams in Java

Example of Streams in Java

Here's an example that demonstrates the use of Streams in Java to filter and transform a collection of names:

In this example, we create a stream from the names list, filter the names starting with "J", convert them to uppercase using the map operation, and collect the results into a new list using the collect terminal operation. The output is the filtered and transformed names: [JOHN, JANE].

How to Create Java Stream?

Java streams can be created in many ways, including creating an empty stream, a stream from an existing array, a stream from specified values, etc. Streams in java are declared as:

Syntax

Depending upon the declaration, T is either a class, object, or data type.

Different Operations on Streams in Java

Stream provides various operations that can be chained together to produce results. Stream operations can be classified into two types.

  • Intermediate Operations
  • Terminal Operations

1. Intermediate Operations

It returns a stream as the output and intermediate operations are only executed once a terminal operation is invoked on the stream. This is called lazy evaluation, which is discussed in detail in the later section (Lazy Evaluation).

2. Terminal Operations

Terminal operations in streams produce the final results of the stream after all intermediate operations have been applied, marking the end of stream processing. Once a terminal operation is executed, the stream cannot be further utilized.

Java Stream Interface Methods

MethodsDescription
Stream<T> distinct()It produces a stream containing unique elements based on their equality defined by the equals method.
Optional<T> findAny()It returns an Optional containing an element from the stream, if present, or an empty Optional if the stream is empty.
void forEach(Consumer<? super T> action)It executes a specific action for every element within the stream.
Stream<T> limit(long maxSize)This method returns a stream containing elements from the original stream, limited to a maximum length of maxSize.
Stream<T> peek(Consumer<? super T> action)It produces a stream containing the elements of the original stream while executing a specified action on each element as it is processed.
Stream<T> sorted()The sorted() method returns a stream with elements sorted in natural order. If the elements are not comparable, it may result in a ClassCastException during terminal operations.
Object[] toArray()It collects the elements of the stream into an array and returns it.
boolean anyMatch(Predicate<? super T> predicate)It retrieves the first element from the stream that matches the given predicate. If the stream is empty, it returns false without evaluating the predicate.
static <T> Stream.Builder<T> builder()It returns a builder for a Stream.
boolean allMatch(Predicate<? super T> predicate)it return all the matched elements with given predicate.
<R,A> R collect(Collector<? super T,A,R> collector)It conducts a mutable reduction operation on the stream elements using a Collector, enabling flexible collection strategies and composing collect operations like grouping or partitioning.
static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b)It creates a concatenated stream by combining elements from two input streams. The resulting stream inherits ordering and parallelism properties from the input streams and invokes close handlers for both when closed.

Example of Java Stream

Output

Conclusion

  1. Streams in Java provide a sequence of objects that support various sequential and parallel aggregate operations.
  2. The Stream API in Java offers both intermediate and terminal operations that can be applied to stream instances.
  3. Intermediate operations, such as filter, map, and sorted, return a new stream and are lazily evaluated, meaning they are only executed once a terminal operation is invoked.
  4. Terminal operations, including forEach, collect, min, and max, produce the final results of the stream.
  5. Some stream operations are short-circuiting, allowing early termination without processing all elements in the stream.
  6. Lazy evaluation is a fundamental characteristic of streams in Java, ensuring that intermediate operations are performed only when a terminal operation is invoked.