map and flatmap in Java8

Vivek Singh
2 min readOct 26, 2021

Map

  • Is a not terminal operation i.e intermediate stream operation
  • Takes a function and is called for every value in the input stream
  • Returns one output value for every input value
  • Returns Stream<R> type
  • Syntax
<R> Stream<R> map(Function<? super T, ? extends R> mapper)
  • Usage Example : Adding a constant number to all elements in the list and returning the stream

FlatMap

  • Is a non terminal operation i.e intermediate stream operation
  • Takes a function and is called for every value in the input stream
  • Returns multiple/arbitary output values for every input
  • Returns Stream<R> type
  • Syntax:
<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper)
  • Usage example : Getting the last character of all strings from a list of list of strings

flatMap is a combination of map and flat operation

Consider a 2D object — [[1,2,3],[1,2,3],[1,2,3,]]. If we use a flatmap on this 2D object, then it will return a 1D or one level structure like [1,2,3,1,2,3,1,2,3]

If a map is used in the same structure instead of a flatmap, it returns the 2D structure :

[1,2,3] [1,2,3] [1,2,3]

Explanation with Java8 Code :

import java.util.ArrayList;
import java.util.List;
public class tempStreams {
public static void main(String[] args) {
List<List<Integer>> list = new ArrayList<>();
List<Integer> tempList = new ArrayList<>();
for(int i=1;i<=3;i++) {
tempList.add(i);
}
for (int j=1;j<=3;j++) {
list.add(tempList);
}
list.stream().map(s -> s).forEach(s->System.out.println(s));
// outputs[1,2,3] [1,2,3] [1,2,3]

list.stream().flatMap(s -> s.stream()).forEach(
s->System.out.println(s));

//outputs 1 2 3 1 2 3 1 2 3
}
}

Add 2 to every element using map in a List of List of Integers:

list = [[1,2,3],
[1,2,3],
[1,2,3]]
List<List<Integer>> lists = list.stream().map(s -> s.stream().map(x -> x+2).collect(Collectors.toList())).collect(Collectors.toList());
for(List s : lists) {
System.out.println(s);
}
//prints [3,4,5] [3,4,5] [3,4,5]

As list is a list of integers. We are using a map operation over the outer list. After that we convert the inner list to a stream and go through each individual element to add 2 and return the list. At the end we again convert the outer stream to a list. So we have list of list of Integers as the output.

Same example using flatmap :

List<Integer> lists = list.stream().flatMap(s -> s.stream().map(x -> x+2)).collect(Collectors.toList());
for(Integer s : lists) {
System.out.print(s);
}
//outputs 3 4 5 3 4 5 3 4 5

With flatmap the output type returned is List of Integers not List of List of Integers. Because the purpose of a flatmap is to flatten the list and return the 1D object type structure.

Conclusion

So we use flatmap when we have to change the structure of a stream object and make it flatter; and we use map to do operations on objects so that for every input there’s just one output.
Happy learning. Cheers !

--

--

Vivek Singh

Software Developer. I write about Full Stack, NLP and Blockchain. Buy me a coffee - buymeacoffee.com/viveksinless