Tech with Maddy

Tech with Maddy

Java 8: Streams

Java 8: Streams

Subscribe to my newsletter and never miss my upcoming articles

Streams have been introduced in Java 8, and like lambda expression, they represent an attempt in bringing functional programming to Java.


A Stream is an interface that resides in the package. It is a series of objects that have several methods which can be executed in a sequential fashion to obtain a certain result.

Don’t confuse Streams with Java I/O streams, it is a different topic!

The traits of a stream are:

  • Sequence of elements: a stream is executed on demand. It doesn’t store any data, nor it modifies the provided data source.
  • Data source: the type of input that a stream can operate on. It takes Collections, Arrays, or Input/Output resources.
  • Pipelining: a stream is a chain of intermediate operations which end with a terminal operation (an operation that cannot be linked to another operation).
  • Aggregate operations: stream supports many methods that can be linked together (this is discussed after).
  • Automatic iterations: stream operations perform all the iterations in the background.

Let’s take a look at the below example:

import java.util.Arrays;
import java.util.List;

public class StreamAPI {

    public static void main(String[] args) {

        List<String> animals = Arrays.asList("dog", "cat", "cow", "Fox", "froG", "fiSh");

                .filter(a -> a.startsWith("f"))


The output is:


So what happened here? Let’s explain it in plain English.

First, we create a List of Strings called animals. This list of animals has a dog, a cat, a cow, a Fox, a froG, and a fiSh. Some letters have been written into capitals on purpose to better showcase what we’re trying to achieve. Then, we perform a sequence of operations. First, we use the filter() method to say that we only want those animals that start with the letter “f”. Then, we use the map() to turn those animals into lowercase, and then the sorted() method to put them in their natural order. In the end, we simply print them.

In short, this whole operation says “Please Java, give me a stream of those animals that start with f, lowercase and in alphabetical order”. The uppercase letters in frog and fish get converted into lowercase letters.

In the code snippet above, we used intermediate and terminal operations. But what are they?

Intermediate operations are those operations that can be connected together and return a stream as a result. These operations are lazily loaded, meaning that they are stored in the memory and only get executed when the terminal operation is called at the end of the pipeline. Examples of intermediate operations are:

  • Filter: the filter method is used to retrieve only certain elements based on given criteria. We used this method to fetch only those animals that start with the letter “f”.
  • Map: the map method is used to change the elements of a stream by applying a function. Before, we used the .toLowerCase() method reference to convert the elements into lowercase letters, and indeed we got frog and fish in lowercase.
  • Sorted: the sorted method sorts the elements in their natural order. Indeed the program above printed fish first and frog after.
  • Limit: it simply returns a stream that contains the top N elements.

Terminal operations are operations that cannot be chained together, and they return non-stream values. They are responsible for producing the end result. Examples of terminal operations are:

  • ForEach: this method is used to iterate through each element. We used the forEach() to print all the filtered, converted, and sorted animals.
  • ToArray: returns an array containing items of a stream.
  • Collect: used to gather the result of processing.
  • Count: it returns the number of elements in a stream.

Well done, you've reached the end of this article about streams! I hope that reading this article has given you a nice understanding of this powerful tool. ☺

Share this