Friday, 6 May 2016

Java8 flatMap Example

Java8 flatMap Example/Tutorial

Java8 introduces a new collection API called the Stream API.
The Stream Collection API supports processing streams of data stored within it.
This API has many advantages which will be elaborated in a consolidated post.


Supported operations in Stream API are :

Stream<String>
Stream<Integer>
Stream<String[]>
Stream<ArrayList<String>>
Stream<Set<String>>

Flattening a Stream makes it more easy to iterate and operate over it.
For these reasons it might be required to flatten the Stream like this.

Stream<String[]>           -->  Stream<String>
Stream<ArrayList<String>>  -->  Stream<String>
Stream<Set<Integer>>       -->  Stream<String>


{{1,2}, {3,4}, {5,6}}             --> flatten --> {1,2,3,4,5,6}
{{"Java","Jcr"},{"Hello","Java"}} --> flatten --> {"Java","Jcr","Hello","Java"}

ATTENTION:One WRONG thing which you might have learnt.
In some websites its said that Stream Operation like (filter, sum, distinct…) will not work without flattening a Stream.
This is absolutely wrong. All operations will work, its just that flattening a Stream will make your job easier.
I will explain these with examples a the end of this article.

1. Convert Stream<String[]> to Stream<String>


package codermag.net.java8;

import java.util.Arrays;
import java.util.stream.Stream;

public class StringArrayToFlatMap {

 public static void main(String[] args) {

  String[][] data = new String[][] 
    { 
     { "Java", "Jcr" },
     { "Hello", "Java" }, 
     { "Coder", "Magnet" } 
    };

  //Converting to Stream<String[]>
  Stream<String[]> dataStream = Arrays.stream(data);

  //Flattening the Stream to Stream<String>
  Stream<String> stringStream = dataStream.flatMap(x -> Arrays.stream(x));

  stringStream.forEach(System.out::println);

 }
}



2. Convert a Stream<List<String>> to Stream<String>


package codermag.net.java8;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;


public class ListToFlatMap {
 public static void main(String[] args) {
  
  
  List<String> list1=new ArrayList<String>();
  list1.add("Hello");
  list1.add("Developers");
  
  List<String> list2=new ArrayList<String>();
  list2.add("Welcome");
  list2.add("To Codermagnet");
  
  List<String> list3=new ArrayList<String>();
  list3.add("Wats");
  list3.add("Up?");
  
    
  List<List<String>> itemList=new ArrayList<List<String>>();
  itemList.add(list1);
  itemList.add(list2);
  itemList.add(list3);

  
  //Converting the List of List<String> to Stream
  //List<List<String>> --> Stream<List<String>>
  Stream<List<String>> listStream=itemList.stream();  
  
  //Flattening the Stream<List<String>>  to  Stream<String> 
  Stream<String> flattenedStream=listStream.flatMap(x -> x.stream());

  flattenedStream.forEach(System.out :: println);
  
  
 }
}



You don't need a flattened Stream to use methods like filter(),sum()....etc

So just to show that you can apply Stream methods here are some examples.



Example 1:
The following example filters arrays whose size is greater than 2.
This shows how you can use filter() on a Stream<String[]> instead of using a flattened Stream<String>.


package codermag.net.java8;

import java.util.Arrays;
import java.util.stream.Stream;

public class FilterWorksOnNonFlattenedStream {

 public static void main(String[] args) {

  String[][] alphabets = new String[][] 
    { 
     { "a", "b" }, 
     { "c", "d" },
     { "e", "f", "g" } 
    };

  Stream<String[]> alphabetStream = Arrays.stream(alphabets);

  // Filtering out the arrays having more than 2 elements
  Stream<String[]> filteredStream = alphabetStream.filter(x -> (x.length > 2));

  filteredStream.forEach(x -> System.out.println(Arrays.toString(x)));
 }
}


OUTPUT:

[e, f, g]



Example 2:
Filtering out List objects which contain the String "Hello".
This shows how you can use filter() on a Stream<List<String>> instead of using a flattened Stream<String>.

package codermag.net.java8;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;


public class FilterWorksOnNonFlattenedStream2 {
 public static void main(String[] args) {
  
  
  List<String> list1=new ArrayList<String>();
  list1.add("Hello");
  list1.add("Developers");
  
  List<String> list2=new ArrayList<String>();
  list2.add("Welcome");
  list2.add("To Codermagnet");
  
  List<String> list3=new ArrayList<String>();
  list3.add("Hello");
  list3.add("WhatsUp?");
  
    
  List<List<String>> itemList=new ArrayList<List<String>>();
  itemList.add(list1);
  itemList.add(list2);
  itemList.add(list3);

  
  //Converting the List of List<String> to Stream
  //List<List<String>> --> Stream<List<String>>
  Stream<List<String>> listStream=itemList.stream();  
  
  //Filtering only the List objects containing the string "Hello"
  Stream<List<String>> filteredList=listStream.filter(x -> x.contains("Hello"));
  
  filteredList.forEach(System.out :: println);
 }
}


OUTPUT:
[Hello, Developers]
[Hello, WhatsUp?]