Tech Master Tutorials
Email Facebook Google LinkedIn Pinterest Twitter
Home Java Java 8 Java Interview Questions Java8 Interview Questions Object Oriented Programming in Java JVM Java Programming

Stream

A Stream APIs have introduced in Java 8 to perform various operations with the collections.
Stream APIs provides utility methods like filter, map, collect, sorted and many other.
Stream APIs can perform serial as well as parallel execution.
We have stream() for serial execution and parallelStream() for parallel execution.

Lets see usage of streams with a simple example.
package streamApi;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

public class StreamTest {
	
	public static void main(String[] args) {
		
		List<String> strList = new ArrayList<>();
		strList.add("mismatch");
		strList.add("mismatch");
		strList.add("match");
		strList.add("match");
		strList.add("match");
		
		System.out.println("size = " + strList.size()); //output
		System.out.println("strList before filter : "+ strList.toString());
		
		List<String> filterdList = strList.stream()
			   .filter(str -> str.equals("match"))
			   .collect(Collectors.toList());
	    
		System.out.println("filterdList size = " + filterdList.size()); //output
		System.out.println("filterdList : "+ filterdList.toString());
		
	}
	
}
In the above example, we have list of strings, and we filtering the list using streams.
First we strList.stream() and get the stream of strings and then collect the stream of strings using the collect() method into a list of strings.


Lets have a look at one more example
package streamApi;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

public class StreamTest {
	
	public static void main(String[] args) {
		
		List<String> strList = new ArrayList<>();
		strList.add("first");
		strList.add("second");
		strList.add("third");
		strList.add("fourth");
		strList.add("");
		strList.add(null);
		
		System.out.println("size = " + strList.size()); //output
		System.out.println("strList before filter and sort : "+ strList.toString());
		
		List<String> filterdList = strList.stream()
			   .filter(str -> str != null && str.trim().length() > 0)
			   .sorted()
			   .collect(Collectors.toList());
	    
		System.out.println("filterdList size = " + filterdList.size()); //output
		System.out.println("filterdList : "+ filterdList.toString());
		
	}
	
}
In the above example, first list of string stream is being filtered on the basis of null and empty check.
Then string stream is being sorted and strings are being collected into a list of Strings.
In streams there are intermediate methods and terminal methods.


Intermediate & Terminal methods :

Stream provides various types of operations. Stream operations are categorized into intermediate and terminal operations.
Intermediate operations are lazy i.e. intermediate operations are not invoked immediately but invoked only when a terminal
operation is applied on the stream.

Lets pick the below stream processing from the above example.
strList.stream()
	.filter(str -> str != null && str.trim().length() > 0)
	.sorted()
       .collect(Collectors.toList());



Here in this example, filter and sorted methods are intermediate methods in stream processing.

Intermediate methods :

  • strList.stream() – return the stream of Strings
    output : Stream of String
  • filter() – return stream of Strings
    output : Stream of String
  • sorted() – sort the stream of Strings
    output: Stream of String

Terminal Methods:

  • collect(Collectors.toList()): Collects the stream of Strings into a List of Strings.
    Output: List of String

Terminal method is where the processing pipeline terminates.
One more difference that is visible by the above description is that –
Intermediate Methods return another stream and terminal methods return object or a collection of objects.

Example of Intermediate Operations :

  • filter()
  • map()
  • sorted()
  • distinct()

Example of Terminal methods :


  • collect() – Used in above examples
  • findFirst() : Returns as soon as stream find the first element fulfilling a given condition.
  • findAny()
  • anyMatch()
  • forEach()


Parallel Streams:

Normal stream() processing is serial. If we can perform operations independently over the stream elements
then we can use parallelStream for better performace().
Lets have a look at the below example :
package streamApi;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

public class ParallelStream {
	
	public static void main(String[] args) {
		
		List<String> strList = new ArrayList<>();
		strList.add("mismatch");
		strList.add("mismatch");
		strList.add("match");
		strList.add("match");
		strList.add("match");
		
		System.out.println("size = " + strList.size()); //output
		System.out.println("strList before filter : "+ strList.toString());
		
		Set<Integer> filterdStringLengthSet = strList.parallelStream()
			   .filter(str -> str.equals("match"))
			   .map(str -> str.length())
			   .collect(Collectors.toSet());
		
		System.out.println("filterdList size = " + filterdStringLengthSet.size()); //output
		System.out.println("filterdList : "+ filterdStringLengthSet.toString());
		
		
		
		Set<Integer> setWithStringLengths = strList.parallelStream()
				   .map(str -> str.length())
				   .collect(Collectors.toSet());
		
		System.out.println("filterdList size = " + setWithStringLengths.size()); //output
		System.out.println("filterdList : "+ setWithStringLengths.toString());
		
	}
	
}
In the above example, we are getting the parallelStream on top of the list items. Parallel stream is going to execute
operations in parallel and then will collect the result into the list at the end of the processing.
Here we are filtering and mapping the strings in parallel and at the end collects the result into a list of Strings.
So if you have a use case where items can be processed independently then you can use parallel stream to process in
parallel to achieve faster processing.