Java Stream API – Introduction

5 min read

Hey Guys!! In this blog post, we will be learning basics of Stream API. After gaining some know-how info, we will be having follow up article to this with Stream operations.

What is a Stream?

A stream is a sequence of elements which can be created from Collections such as List of Arrays or any kind of I/O.

Stream API was introduced in Java 8. Its main objective is to perform operations on Collections. It made Parallel operations easy to perform without having to spawn actual thread per operation.

Streams can be created sequentially or parallely.

List<String> listOfNames = Arrays.asList("Adam", "Neel");
listOfNames.stream() //creates a sequential stream
listOfNames.parallelstream() //creates a parallel stream

How JAVA 8 Stream works?

Streams consist of a source, that is the source of streams or sequence of Collections, zero or more intermediate operations and a terminal Operations. Combining all of them results in a stream Pipeline. A stream pipeline must have a terminal operation in order to work.

Intermediate operation always returns a new stream. It is invoked lazily; It does not return the same stream on which it is applied, it creates a new stream, applies the given predicate and based on the result, gives a new stream. This new stream cannot be traversed until the terminal operation is completed.

After the terminal operation is completed, stream pipeline is considered to be consumed. In order to traverse on resultant stream, it must be returned. Almost all the terminal operations operates eagerly.

Intermediate operations can be stateless or stateful. Filter and map are examples of stateless operations which does not hold any state of streams. Wherein, sorting cannot be performed until every element in a stream is traversed and processed. therefore it maintains a state of traversed elements.

Pipelines containing exclusively stateless intermediate operations can be processed in a single pass, whether sequential or parallel, with minimal data buffering.

Below is the basic example of a stream pipeline.

public class StreamPipelineExample {
 
    public static void main(String a[]) {
 
        List<String> listOfVehicles = Arrays.asList("bus", "car", "bicycle", "flight", "train");
 
        listOfVehicles.stream() //create a stream
                      .filter(str->str.length() >3) //intermediate
                      .map(String::toUpperCase) //intermediate
                      .sorted() // stateful intermediate
                      .forEach(System.out::println);; // terminal
    }
}

In the above example, first a stream is created from the Collection, then a filter and map intermediate operations are applied. Further, sorting is applied which is stateful in nature. All intermediate operations will return a new stream based on the applied predicate. Finally, forEach is applied as a terminal operation and the pipeline is consumed.

Collections vs Streams

In Collection we can add and delete elements but in stream we cant; It is fixed.

In Collection, we can access elements randomly; For ex, retrieving elements from list via index. Bit in stream we can access elements only sequentially.

Collections is eagerly constructed; Stream is lazily constructed. Collection can be traversed multiple times but a stream can be traversed only once. Collection follows external iteration and stream follows internal iteration.

I hope, after reading this, you must be having basic gist of Stream API. Further, in the next blog post we will be learning Stream operations with practical examples.

Happy Learning!!