To explain what parallel streams are, we need to first talk about what exactly a Java Stream is. Java Streams were introduced in Java 8, and are used to process a collection of objects which can be pipelined to produce a desired result.

A stream itself is not a data structure, it instead takes its input from collections, arrays, or other I/O channels. Additionally, streams don’t change the original data structure and only return results based on pipelined methods.

In a stream, intermediate operations are lazily executed and return results in the form of additional streams, which allow for the pipelining of those results. Terminal operations mark the end of the stream and return the final result.

An operation is lazy if its value is evaluated only when it is required. The reason why it does this is to save the processing of actual stream contents until the terminal operation commences. This enables the Java compiler and runtime to optimize how they process streams.

Let’s go over some different types of operations.

Intermediate Operations:

  • map: returns a stream consisting of the results after applying a given function to the elements of this stream
List numbers = Arrays.asList(1,2,3,4); List square = numbers.stream().map(x->x*x).collect(Collectors.toList());
  • filter: selects elements as per a Predicate passed as an argument
List names = Arrays.asList(“Alpha”,”Beta”,”Omega”); List find = names.stream().filter(s->s.startsWith(“O”)).collect(Collectors.toList());
  • sorted: sorts the stream
List names = Arrays.asList(“Omega”,”Alpha”,”Beta”); List sorted = names.stream().sorted().collect(Collectors.toList());

Terminal Operations:

  • collect: returns the result of the intermediate operations performed on the stream
List numbers = Arrays.asList(1,2,3,4,2); Set squareSet = numbers.stream().map(x->x*x).collect(Collectors.toSet());
  • forEach: iterates through every element of the stream
List numbers = Arrays.asList(1,2,3,4); numbers.stream().map(x->x*x).forEach(y->System.out.println(y));
  • reduce: reduces the elements of a stream to a single value (this takes a BinaryOperator as a parameter)
List numbers = Arrays.asList(1,2,3,4); int even = numbers.stream().filter(x->x%2==0).reduce(0,(ans,i)->ans+i);

In the above example, ans is a variable that is assigned the value 0 initially, then i is added to it.

Remember, everything a stream does has no effect on the original value of the object initially passed to it.



Streams may be confusing at first with all the intermediate operations in place and terminal operations, but an easy way to look at and use streams is as follows:

“A stream is a series of intermediate operations up to a terminal operation.”

All those intermediate operations are computed and the eventual result is returned upon the final processing of that terminal operation.

Let’s take a closer look at an example of a stream and break it down.

Add these lines to main():

List<Integer> number = Arrays.asList(1,2,3,4); List<Integer> square = number.stream().map(x -> x*x).collect(Collectors.toList()); System.out.println("Squares: " + square);

Here, we create a list of integers, and because List is a Collection we can stream it. This particular stream is just taking a list of numbers, computing their squares one by one, and returning a new list of those squared results. To do this, we stream() the number list and then map it with the function x -> x*x (i.e. for each element of the list, apply this function to it).

To get our result, we can call the terminal operation collect and tell it to perform the collection as a List. This result is stored in a new List called square.

Run the code and see the results.


Let’s do another one.

Add these lines to main():

List<String> names = Arrays.asList("Omega","Alpha","Beta"); List<String> find = names.stream().filter(s->s.startsWith("O")).collect(Collectors.toList()); System.out.println("Name starts with O: " + find);

This stream applies a filter onto each string element of the streamed List, collecting any string that starts with the letter “O”.

Run the code and see the results.


Here are the rest of the examples we discussed in the lesson. Add them to your code and try to decipher what they do:

List<String> sorted = names.stream().sorted().collect(Collectors.toList()); System.out.println("Sorted names: " + sorted);
List<Integer> numbers = Arrays.asList(1,2,3,4,1,2); Set<Integer> squareSet = numbers.stream().map(x->x*x).collect(Collectors.toSet()); System.out.println("Square set: " + squareSet);
number.stream().map(x->x*x).forEach(y->System.out.println(" intermediate square: " + y));
int even = number.stream().filter(x->x%2==0).reduce(0,(ans,i)-> ans+i); System.out.println("Reduce evens: " + even);

Run the code and see the results.

Sign up to start coding

Mini Info Outline Icon
By signing up for Codecademy, you agree to Codecademy's Terms of Service & Privacy Policy.

Or sign up using:

Already have an account?