Stream Operations: Intermediate, Terminal

Ankit P. Karve
3 min readMay 22, 2021
Conecpt of stream

Well Java Stream is very useful feature provided by Java8
Basically Stream is provided to help in processing Collections or group of objects
Stream doesn’t actually hold data it just process data
There are many ways of creating stream like using Stream.of() or collectionObj.stream() then we perform operation on data and after processing we have to collect data from streams

Most of the things have types based on characteristics of it similarly Operation performed on streams also have different types.
Those types are Intermediate, Terminal. This types are differentiates in which manner operations are performed.

Intermediate Operations
1. map
2. filter
3. skip
4. sorted
5. flatMap
Intermediate operations are lazy. Lazy means they didn’t proceed things till we perform any terminal operation on it.
Intermediate operation gives another new or processed stream based on stream on which we are performing operation.
Intermediate operations can be chained means if we called skip() on stream then we can call map() on it like stream.skip(1).map().

Terminal Operations
1. forEach
2. collect
3. min
4. max
5. reduce
6. count
Terminal operations are not lazy, they execute immediately. Terminal operations doesn’t return stream, they return collection or primitive values. and terminal operations cannot be chained because previous terminal option doesn’t return stream. So we can perform only one terminal operation on single stream.

below is example of Intermediate and terminal operation:
We have collection which have country names in it :


ArrayList<String> countries = new ArrayList<>();
countries.add(“India”);
countries.add(“Australia”);
countries.add(“USA”);
countries.add(“Israil”);
countries.add(“England”);

We will get stream from collection object countries by calling stream() method

Stream<String> countryStream = countries.stream();

Now we will call filter method with predicate that will return country names that starts with “I”.

countryStream.filter(country -> country.startsWith(“I”));

As said above even if we have called filter with predicate still code will not execute because filter is intermediate operation so it is lazy, it will not get called till we perform terminal operation on it.

countryStream.filter(country -> country.startsWith("I"))
.forEach(countryName -> System.out.println(countryName));

above code will print India and Israil as we have performed terminal operation on it. So it will execute filter operation then it will print that using in forEach. If we want to get data in another object we can use collect() operation.

Intermediate operations that we perform using stream some have stateful behaviour and some are stateless. Stateless operation doesn’t maintain states while executing function on source data.

In above example we used filter intermediate operation which is stateless.
lets see example of stateful intermediate operation.

ArrayList<String> fruits = new ArrayList<>();
fruits.add(“Mango”);
fruits.add(“Banana”);
fruits.add(“Apple”);
fruits.add(“Banana”);
Stream<String> fruitStream = fruits.stream();
fruitStream.distinct()
.forEach(fruit -> System.out.println(fruit));

skip, distinct, sorted, limit are stateful operations. Stateful operation need to maintain their state while processing data. like in above example we performed distinct operation which gives us distinct names of fruit so it will print ‘Banana’ only on time. So to ignore repeated data and give distinct elements it is important to maintain state during passes.
******************************************************************

Hope so this is helpful to you. If you liked my article and you want to know more about my future articles, you can follow me in Medium.

--

--