In this article, we will discuss some important and frequently asked Java 8 Stream API Interview Questions and Answers.
YouTube Video
1. What is a Stream?
You can use Stream to filter, collect, print, and convert from one data structure to another, etc.
Stream does not store elements. It simply conveys elements from a source such as a data structure, an array, or an I/O channel, through a pipeline of computational operations.
Stream is functional in nature. Operations performed on a stream do not modify its source. For example, filtering a Stream obtained from a collection produces a new Stream without the filtered elements, rather than removing elements from the source collection.
2. Explain Stream Operations?
Stream operations are divided into intermediate and terminal operations,Java Stream Example: Filtering using Stream.filter() method:
List < Product > productsList = new ArrayList < Product > (); // Adding Products productsList.add(new Product(1, "HP Laptop", 25000 f)); productsList.add(new Product(2, "Dell Laptop", 30000 f)); productsList.add(new Product(3, "Lenevo Laptop", 28000 f)); productsList.add(new Product(4, "Sony Laptop", 28000 f)); productsList.add(new Product(5, "Apple Laptop", 90000 f)); // This is more compact approach for filtering data productsList.stream().filter(product -> product.getPrice() == 30000) .forEach(product -> System.out.println(product.getPrice()));
Output:
30000.0
List < Product > productsList = new ArrayList < Product > (); // Adding Products productsList.add(new Product(1, "HP Laptop", 25000 f)); productsList.add(new Product(2, "Dell Laptop", 30000 f)); productsList.add(new Product(3, "Lenevo Laptop", 28000 f)); productsList.add(new Product(4, "Sony Laptop", 28000 f)); productsList.add(new Product(5, "Apple Laptop", 90000 f)); // Converting product List into Set Set < Float > productPriceList = productsList.stream().filter(product -> product.getPrice() < 30000) .map(product -> product.getPrice()).collect(Collectors.toSet()); System.out.println(productPriceList);
List<String> stringList = new ArrayList<>();
stringList.add("one");
stringList.add("two");
stringList.add("three");
stringList.add("one");
Stream<String> stream = stringList.stream();
stream.forEach( element -> { System.out.println(element); });
Output:
one
two
three
one
Example 2: Stream min() and max()
List < Product > productsList = new ArrayList < Product > (); // Adding Products productsList.add(new Product(1, "HP Laptop", 25000f)); productsList.add(new Product(2, "Dell Laptop", 30000f)); productsList.add(new Product(3, "Lenevo Laptop", 28000f)); productsList.add(new Product(4, "Sony Laptop", 28000f)); productsList.add(new Product(5, "Apple Laptop", 90000f)); // max() method to get max Product price Product productA = productsList.stream() .max((product1, product2) -> product1.getPrice() > product2.getPrice() ? 1 : -1).get(); System.out.println(productA.getPrice()); // min() method to get min Product price Product productB = productsList.stream() .max((product1, product2) -> product1.getPrice() < product2.getPrice() ? 1 : -1).get(); System.out.println(productB.getPrice());
3. How to Create Streams in Java?
Here are the examples to create a Stream using different sources such as Array, Collections, String, etc.
Creating Empty Stream
The empty() method should be used in case of the creation of an empty stream:
Stream<String> stream = Stream.empty();
stream.forEach(System.out::println);
Creating Stream from From Collections
A stream can be created of any type of Collection (Collection, List, Set):
Collection<String> collection = Arrays.asList("JAVA", "J2EE", "Spring", "Hibernate");
Stream<String> stream2 = collection.stream();
stream2.forEach(System.out::println);
List<String> list = Arrays.asList("JAVA", "J2EE", "Spring", "Hibernate");
Stream<String> stream3 = list.stream();
stream3.forEach(System.out::println);
Set<String> set = new HashSet<>(list);
Stream<String> stream4 = set.stream();
stream4.forEach(System.out::println);
Creating Stream object from Arrays
An Array can be a source of a Stream or an Array can be created from the existing array or of a part of an array: // Array can also be a source of a Stream
Stream<String> streamOfArray = Stream.of("a", "b", "c");
streamOfArray.forEach(System.out::println);
Creating Stream object from String using chars() method
IntStream streamOfChars = "abc".chars();
Read more about streams at Java 8 Stream APIs with Examples.
4. What is the difference between Collections API and Streams API?
1. Collections are used to store and group the data in a particular data structure like List, Set, or Map. Whereas Streams are used to perform complex data processing operations like filtering, matching, mapping, etc on stored data such as arrays, collections, or I/O resources. That means, collections are mainly about data and streams are mainly about operations on data.Example 1: List collection is used to store data
// Creating an ArrayList of String using List<String> fruits = new ArrayList<>(); // Adding new elements to the ArrayList fruits.add("Banana"); fruits.add("Apple"); fruits.add("mango"); fruits.add("orange");
Example 2: Streams are used to perform operations like filtering, mapping, collection result, etc:
List<String> lines = Arrays.asList("java", "c", "python");
List<String> result = lines.stream() // convert list to stream
.filter(line -> !"c".equals(line)) // we dont like c
.collect(Collectors.toList()); // collect the output and convert streams to a List
result.forEach(System.out::println);
For example:
// Creating an ArrayList of String using List < String > fruits = new ArrayList < > (); // Adding new elements to the ArrayList fruits.add("Banana"); fruits.add("Apple"); fruits.add("Mango"); fruits.add("Orange"); fruits.add("Pineapple"); fruits.add("Grapes"); System.out.println(fruits); // Remove the element at index `5` fruits.remove(5); System.out.println("After remove(5): " + fruits);
In Streams, there are no such methods to add or remove elements.
On the other hand, you have to do the iteration externally over collections using loops.
Example 1: External iterations of Collections using for loops
// Creating an ArrayList of String using List<String> fruits = new ArrayList<>(); // Adding new elements to the ArrayList fruits.add("Banana"); fruits.add("Apple"); fruits.add("mango"); fruits.add("orange"); fruits.add("Watermelon"); fruits.add("Strawberry"); System.out.println("\n=== Iterate using for loop with index ==="); for(int i = 0; i < fruits.size(); i++) { System.out.println(fruits.get(i)); } System.out.println("=== Iterate using Java 8 forEach and lambda ==="); fruits.forEach(fruit -> { System.out.println(fruit); });
Example 2: Internal iteration of Streams. No more for loops:
List<String> lines = Arrays.asList("java", "c", "python");
List<String> result = lines.stream() // convert list to stream
.filter(line -> !"c".equals(line)) // we dont like c
.collect(Collectors.toList()); // collect the output and convert streams to a List
result.forEach(System.out::println);
List<Integer> numbers = Arrays.asList(4, 2, 8, 9, 5, 6, 7); Stream<Integer> numbersGreaterThan5 = numbers.stream().filter(i -> i > 5); //Traversing numbersGreaterThan5 stream first time numbersGreaterThan5.forEach(System.out::println); //Second time traversal will throw error //Error : stream has already been operated upon or closed numbersGreaterThan5.forEach(System.out::println);
5. What does the Stream map() function do? why you use it?
The map() function is an intermediate function that is used to perform map functional operations in Java. This means it can transform one type of object to others by applying a function.Use map() function to convert one object to another object.
For example, if you have a List of String and you want to convert that to a List of Integer, you can use map() to do so.
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class Main
{
public static void main(String[] args)
{
List<String> listOfStrings = Arrays.asList("1", "2", "3", "4", "5");
List<Integer> listOfIntegers = listOfStrings.stream()
.map(Integer::valueOf)
.collect(Collectors.toList());
System.out.println(listOfIntegers);
}
}
Output:
[1, 2, 3, 4, 5]
6. What does the Stream filter() method do? when you use it?
Java stream provides a filter() method to filter stream elements on the basis of a given predicate. This method takes a predicate as an argument and returns a stream consisting of resulted elements.Example 1: Using filter() method to filter List of string objects:
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class Tester {
public static void main(String[] args){
List<String> lines = Arrays.asList("java", "c", "python");
List<String> result = lines.stream() // convert list to stream
.filter(line -> !"c".equals(line)) // we dont like c
.collect(Collectors.toList()); // collect the output and convert streams to a List
result.forEach(System.out::println);
}
}
Output:
java
python
Example 2: In this example, we will create a list of products and we filter products whose price is greater than 25k. We display a list of products using the forEach() method.
Let's first create a Product class:
class Product { private int id; private String name; private float price; // getters and setters }
public class StreamFilterExample { public static void main(String[] args) { // using stream API List < Product > filteredProducts = getProducts().stream() .filter((product) -> product.getPrice() > 25000 f) .collect(Collectors.toList()); filteredProducts.forEach(System.out::println); } private static List < Product > getProducts() { List < Product > productsList = new ArrayList < Product > (); productsList.add(new Product(1, "HP Laptop", 25000 f)); productsList.add(new Product(2, "Dell Laptop", 30000 f)); productsList.add(new Product(3, "Lenevo Laptop", 28000 f)); productsList.add(new Product(4, "Sony Laptop", 28000 f)); productsList.add(new Product(5, "Apple Laptop", 90000 f)); return productsList; } }In the above example, we are using the filter() method to filter products whose price is greater than 25k:
List < Product > filteredProducts = getProducts().stream() .filter((product) -> product.getPrice() > 25000 f) .collect(Collectors.toList());
7. What does the Stream flatmap() function do? why you need it?
The Stream.flatMap() function, as the name suggests, is the combination of a map and a flat operation. This means you first apply the map function and then flatten the result.To understand what flattening a stream consists in, consider a structure like [ [1,2,3],[4,5,6],[7,8,9] ] which has "two levels". It's basically a big List containing three more List. Flattening this means transforming it in a "one level" structure e.g. [ 1,2,3,4,5,6,7,8,9 ] i.e. just one list.
For example: In the below program, you can see that we have three lists that are merged into one by using a flatMap() function.
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args)
{
List<Integer> evens = Arrays.asList(2, 4, 6);
List<Integer> odds = Arrays.asList(3, 5, 7);
List<Integer> primes = Arrays.asList(2, 3, 5, 7, 11);
List<Integer> numbers = Stream.of(evens, odds, primes)
.flatMap(list -> list.stream())
.collect(Collectors.toList());
System.out.println("flattend list: " + numbers);
}
}
Output:
flattend list: [2, 4, 6, 3, 5, 7, 2, 3, 5, 7, 11]
8. Difference Between Stream map() and flatMap() Functions
The key difference between map() vs flatMap() in Java 8:- The function you pass to the map() operation returns a single value.
- The function you pass to flatMap() operation returns a Stream of value.
- flatMap() is a combination of map and flat operation.
- map() is used for transformation only, but flatMap() is used for both transformation and flattening.
9. What is the difference between intermediate and terminal operations on Stream?
The intermediate Stream operation returns another Stream, which means you can further call other methods of Stream class to compose a pipeline.
Intermediate Stream operations:
- filter()
- map()
- flatMap()
- distinct()
- sorted()
- peek()
- limit()
- skip()
For example, after calling filter() you can still call the map() method on Stream.
// Converting product List into Set Set < Float > productPriceList = productsList.stream().filter(product -> product.getPrice() < 30000) .map(product -> product.getPrice()).collect(Collectors.toSet());
Stream terminal operation produces a result other than Streams like a value or a Collection.
Terminal Stream operations:
- anyMatch()
- allMatch()
- noneMatch()
- collect()
- count()
- findAny()
- findFirst()
- forEach()
- min()
- max()
- reduce()
- toArray()
Once a terminal method like forEach() or collect() is called, you cannot call any other method of Stream or reuse the Stream.”
List<String> lines = Arrays.asList("java", "c", "python");
List<String> result = lines.stream() // convert list to stream
.filter(line -> !"c".equals(line)) // we dont like c
.collect(Collectors.toList()); // collect the output and convert streams to a List
result.forEach(System.out::println);
Comments
Post a Comment
Leave Comment