FlatMap on an Array or Stream

A first encounter with functional programming is usually using the functions filter , map , or reduce (aka fold) in whichever language/library you're currently using. These are different than typical functions because they take a function as a parameter which specifies part of the operation being performed.

A less commonly used one is flatMap that is similar to map but given a list and a function the supplied function is expected to return a list for each element of the input list. If these parameters were provided to the normal map function, the result would be a list of lists. When given to flatMap the output is a single list with the results from operating on each element concatenated together, hence the flatMap name.

$ jshell

jshell> System.out.println(Stream.of(1, 2, 3).map((x) -> Arrays.asList(-x, x)).collect(Collectors.toList()));
[[-1, 1], [-2, 2], [-3, 3]]

jshell> System.out.println(Stream.of(1, 2, 3).flatMap((x) -> Stream.of(-x, x)).collect(Collectors.toList()));
[-1, 1, -2, 2, -3, 3]

Note: in the map example above, the function returns Arrays.asList rather than a Stream.of values, as doing so would return the result type List<Stream<Integer>> that doesn't print its contents.

In this case for each input number the function returns a list of two numbers the negation and the number itself. It is not required for the function to return a fixed size list. For any input it can return an list of zero, one, or more elements.

Stream.of(0, 1, 2, 3).map((x) -> x.equals(0) ? Collections.emptyList() : Arrays.asList(-x, x)).collect(Collectors.toList())
==> [[], [-1, 1], [-2, 2], [-3, 3]]

Stream.of(0, 1, 2, 3).flatMap((x) -> x.equals(0) ? Stream.empty() : Stream.of(-x, x)).collect(Collectors.toList())
==> [-1, 1, -2, 2, -3, 3]

Notice that each empty Array or Stream returned by the function just 'disappears' from the output of flatMap like it wasn't even there.

Last updated

Was this helpful?