I am working with Streams (Java 8) and when I use the .stream()
method it is not clear to me the difference between .map
and .flatMap
. What are the differences between these methods?
I am working with Streams (Java 8) and when I use the .stream()
method it is not clear to me the difference between .map
and .flatMap
. What are the differences between these methods?
The difference is that map()
returns the same number of elements as the input Stream since it is simply a projection of the input elements. In other words, each input element is transformed into an output element.
On the other hand .flatMap()
, projects a list of elements of each original element and concatenates them into a single stream .
For example:
List<Integer> numeros = new ArrayList<Integer>(Arrays.asList(1, 2, 3, 4)); // [1, 2, 3, 4]
List<Integer> cuadrados = numeros
.stream()
.map( x -> x * x)
.collect(Collectors.toList());
for (Integer n : cuadrados) {
System.out.println(n);
}
// Imprime el cuadrado de los números de entrada. 4 elementos de entrada, 4 de salida
// 1
// 4
// 9
// 16
List<List<Integer>> listaBidimensional = new ArrayList<List<Integer>>(Arrays.asList(
new ArrayList<Integer>(Arrays.asList(1, 2)),
new ArrayList<Integer>(Arrays.asList(3, 4))
));
// [
// [1, 2],
// [3, 4]
// ]
List<Integer> listaAplanada = listaBidimensional
.stream()
.flatMap( listaInterna -> listaInterna.stream())
.collect(Collectors.toList());
for (Integer n : listaAplanada) {
System.out.println(n);
}
// Imprime los números de entrada en una sola lista de 1 dimensión.
// 2 elementos de entrada (2 listas), 4 de salida
// 1
// 2
// 3
// 4
The difference is that .map produces an output value for each input value and .flatmap produces zero output values for each input value, more or less in the following way:
map :: Stream T (I - > O) flapmap :: Stream T (I -> Stream O)
I have attached an example code:
public class Developer {
private String name;
private Set<String> languages;
public Developer(String name) {
this.languages = new HashSet<>();
this.name = name;
}
public void add(String language) {
this.languages.add(language);
}
public Set<String> getLanguages() {
return languages;
}
}
public class FlatMapTest {
@Test
public void flatMap() {
List<Developer> team = new ArrayList<>();
Developer polyglot = new Developer("experto");
polyglot.add("clojure");
polyglot.add("scala");
polyglot.add("groovy");
polyglot.add("go");
Developer busy = new Developer("estandard");
busy.add("java");
busy.add("javascript");
Developer becario = new Developer("becario");
team.add(polyglot);
team.add(busy);
team.add(becario);
List<String> teamLanguages = team.stream().
map(d -> d.getLanguages()).
flatMap(l -> l.stream()).
collect(Collectors.toList());
assertTrue(teamLanguages.containsAll(polyglot.getLanguages()));
assertTrue(teamLanguages.containsAll(busy.getLanguages()));
}
}