Streams in Java

When Java 8 came into the picture, a significant new functionality came into existence, that is, Java Streams. You should not confuse Java Streams with the Java I/O Streams, as these have little to do with each other. Streams are used to process a collection of objects. Think of these streams as wrappers around a data source. In this article, we will discuss Streams in detail with explained example codes. So, let`s begin.

Why Streams?

Let us take an example to understand why and where streams are used in the first place. Say, you want to add all the numbers of a list which is greater than 10. The traditional method to do that would be the following.


Let us look at the output of the above code.

Operation on a List without Streams.
Fig.1- Operation on a List without Streams.

Great! We got the answer as 27. There are two numbers in the list higher than 10, which are 11 and 16, and the sum of those numbers adds up to 27.
Now, let`s see how we can write the above code in a single line using Java Streams.


Let us look at the output of the above code.

Why Streams are used in Java?
Fig.2- Why Streams are used in Java?

See! We got the same output. We can use Java Stream API to implement internal iteration. It helps in a bunch of features such as sequential and parallel execution, filtering, mapping, etc.

Creating a Stream

Streams are created from different element sources such as collection or array with the help of stream() and of() methods. Let us see how to create a stream.

Java Streams Operations and Pipelines

Java Streams operations are divided into two categories.

  • Intermediate operations
  • Terminal operations.

These operations are combined to form pipelines. A stream pipeline consists of a source such as Collection, Array or an I/O channel. These sources are followed by zero or more intermediate operations such as Stream.filter,, Stream.sorted and a terminal operation such as Stream.forEach or Stream.reduce.
Intermediate operations return a new stream. By executing an intermediate operation such as filter(), it does not filter the given stream, but instead creates a new stream that, when traversed, contains the elements of the initial stream that match the given order.
Terminal operations, such as Stream.forEach traverses the stream to produce a result. After performing the terminal operation, the stream pipeline is considered exhausted and can no longer be employed. If you need to traverse the same data source again, you must return to the data source to get a new stream.
Enough of all the theory, let us jump to some example code to understand the operations and pipelines of Java Streams.


Let us first look at the output of the above example code.

Java Streams Example
Fig.3- Java Streams Example

Let me break down the above code for you and explain it bit by bit. After creating a list of integers, which is, [2, 3, 4, 5]. For any operation of stream, the common format to do that is, -> operationOnVariable).collect(Collectors.toList());
Instead of collect.(Collectors.toList()); we can use other terminal operations as per our requirement.
In the Map method, we are finding the cube of the given list of integers. In the next part, we are creating a list of strings. In the filter method, using the startsWith method we filter the string starting with the letter ‘S.’ In the sorted method, we are arranging the given list in the alphabetical order.


Java Streams is a sequence of objects which supports several methods. It can be pipelined to produce the desired result.
Let us summarize the Stream operations we have seen in this article.

  • Map: It produces a new stream from the original stream after applying an operation to each element of the original stream.
  • Filter: It produces a new stream from the original stream after passing the given condition.
  • Sorted: It produces a new stream from the original stream after sorting the stream.
  • Collect: To get the final stream once all operations are performed.

Read More

Author : Satyam Kumar -

You will also like: