Java Stream API tutorial

Java: back to basics.
Reading Time: 3 minutes

Java Stream API was one of the major features released with Java 8, that let you code in declarative style.

It supports function-style operations on streams of elements, such as map, filter and various other transformations.

Streams vs Collection

It is a myth that Java Stream API have replaced Collections in Java. Most of the collections are a main source for the stream to work on and they are often used together.

Some of the major difference between Streams and Collection are:

StorageStorage of data. Collections are about data.No storage of data. Streams are about computations on data
Data ModificationCan add/remove elementsFunctional in nature. Operations on stream eg. filtering will result in a new Stream
IterationExternal iteration on Collections using loops
Perform iteration internally
TraversalCan be traversed multiple timesTraversable only once
EvaluationEager evaluation; All elements are computed in the beginning itselfLazy evaluation; Intermediate operations are not evaluated until terminal operation is invoked.

Creating a Stream

String[] arr = {"d", "b", "c"};
System.out.println("Sorted Stream: " + Stream.of(arr).sorted().collect(Collectors.toList()));

The above code snippet creates a Stream from using Stream.of() and sorts the stream in its natural order, returning a sorted list as output.

Stream Operations

Intermediate operations

Intermediate operations are the ones that return the stream itself. Some of them are:


It accepts a predicate to filter all elements of the stream. This operation acts as an intermediate by enabling us to call another stream operation on the result.

For example, -> str.startsWith("K"))


map lets you convert the given element into another object. -> str.startsWith("K"))

Terminal Operations

Terminal operations return a result of a certain type instead of returning a Stream.


It helps in iterating over all elements of a stream and perform some operation on the elements.



Collect is a useful terminal operation used  to transform the elements of the stream into a different kind of result, e.g. a List, Set or Map.

It accepts a Collector which consists of four different operations: a supplier, an accumulator, a combiner and a finisher.

Java 8 onwards supports various built-in collectors via the Collectors class.

List<String> namesInUppercase =


The reduction operation combines all elements of the stream into a single result.

Optional<String> reduced =
.reduce((s1,s2) -> s1 + "@" + s2);


Short circuiting operations

Short-circuiting operations allow the computations on infinite streams to complete in finite time. Some of the short-citcuiting operations are:


It limits the stream elements to process.

int [] arr = {1,2,3,4,5,6,7,8,9,11};

findFirst(), findAny()

firstFist() returns the first element from the Stream.
findAny() returns any element from the Stream. It may be possible to get a different result every time with findAny() operation.

int [] arr = {1,2,3,4,5,6,7,8,9};
Integer findFirstElem = -> (i%2) == 0)

Integer findAnyElem = -> (i%2) == 0)

allMatch(), anyMatch()

These short circuit operators returns true or false value depending on the condition being evaluated.
allMatch() evaluates the condition for all the steams and will return a boolean value.

anyMatch() evaluates the condition in the stream until it finds its match and once the match is found, It exits the processing and returns a boolean value.

int [] arr = {1,2,3,4,5,6,7,8,9,11};
System.out.println("All numbers are greater than -1 : " +> i > -1));

System.out.println("Contains any numbers greater than 10 : " +> i > 10));


Written by 

Himani is a Software Consultant, having experience of more than 2.5 years. She is very dedicated, hardworking and focussed. She is Familiar with C#, C++, C , PHP, Scala and Java and has interest in Functional programming. She is very helpful and loves to share her knowledge. Her hobbies include reading books and cooking.