Java Streams

Observing the Stream and Stream Pipeline

December 5, 2019
List<Book> PopularHorrorBooks = books.stream()
				.filter((book) -> book.getGenre().equalsIgnoreCase("Horror") ) 
				.filter((book) -> book.getRating() > 3) 
				.collect(Collectors.toList());

Consider the book example, This looks like a pipeline of operations on the stream. Break it up to multiple steps:

Creation of Stream

Stream method on Collection will return a Stream of all the elements present in that collection.

//assigning it to appropriate Type - a Stream of Books.
	Stream<Book> stream = list.stream();		

Filtering the Stream

To filter out stream to have only horror books: This operation is performed on the stream returned in the last step (stream). And this will create another new stream.

Stream<Book> horrorBooks = stream.filter((book) -> book.getGenre().equalsIgnoreCase("Horror")) ;

To filter out the stream to have horror books with a rating more than 3: This operation is performed on the stream returned in the last step (horrorBooks). And this will create another new stream.

Stream<Book> popularHorrorBooks = horrorBooks.filter((book) -> book.getRating() > 3);

Collecting the data

To collect this data into a container or to consume the data: We have collect method to collect data; store it in a list.

List<Book> horrorWishList = popularHorrorBooks.collect(Collectors.toList());

This sequence of operations is termed as pipeline, which is called Stream Pipeline.

Stream Pipeline

A stream pipeline consists of a

  • Source – from which we generate the Stream (Collection, Array, Generator function, I/O channel)
  • Intermediate Operations – Operations that are applied on a stream and return another stream
  • A Terminal operation – Produces the result or side effect from the Stream
Stream Pipeline

Source is the list from which we are generating the stream.

Two filter operations, which are Intermediate Operations, as they are applied on stream and they return another stream.

Collect call is the Terminal operation where we are taking the result into a collection. This produces a non-stream result such as primitive value. (Or no value at all)

Streams are not container

Streams are not something to store data inside it. It is just like a fancy iterator.

When we call stream() on the list books, it creates a stream for all of its elements. The filter will be invoked on that created stream.

This filter will filter out the horror genre books and return another new stream.

Again the filter with different predicate will get invoked on the newly generated stream which is having b3, b4 in it.

Now, b4 is having ratings more than 3, it will be filtered out and returned as another new stream.

Now to collect the output in a list, the collect will be invoked on the newly generated stream (stream3), and return a list with the item b4.