Site Search:

Use flatMap() methods in the Stream API

Back>


flatMap() for Stream

stream.flatMap()
stream.flatMap()

<R> Stream<R> flatMap(<Function<? super T, ? extends Stream<? extends R>> mapper)

The method flatMap() is an intermediate stream action, it takes a stream of object, most likely collection, or something can be turned into collection, it then gets a stream from each object with the mapper, finally combines them into a returned stream.

The flatMap() operation has the effect of applying a one-to-many transformation to the elements of the stream, and then flattening the resulting elements into a new stream.

OCPJP>cat FlatMapDemo.java 
import java.util.*;
import java.util.stream.*;
public class FlatMapDemo {
    public static void main(String... args) {
        List<Integer> a = Arrays.asList(1, 2);
        List<Integer> b = Arrays.asList(2, 5);
        List<List<Integer>> c = Arrays.asList(Arrays.asList(5, 2), Arrays.asList(0));
        
        System.out.println("======Stream<List<Integer>> test1 = Stream.of(a, b):");
        Stream<List<Integer>> test1 = Stream.of(a, b);
        test1.flatMap(l -> l.stream()).forEach(System.out::println);
         
        System.out.println("======Stream<List<?>> test2 = Stream.of(a, b, c):");
        Stream<List<?>> test2 = Stream.of(a, b, c);
        test2.flatMap(l -> l.stream()).forEach(System.out::println);
        
        System.out.println("======Stream<List<Integer>> test3 = Stream.of(c):");
        Stream<List<List<Integer>>> test3 = Stream.of(c);
        test3.flatMap(l -> l.stream()).collect(Collectors.toList()).stream().flatMap(l -> l.stream()).forEach(System.out::println);
        
        System.out.println("======flat a stream of sentences:");
        Stream<String> test4 = Arrays.asList("I like aplle", "I like orange", "I dislike vegi").stream();
        test4.flatMap(line -> Stream.of(line.split(" +"))).forEach(System.out::println);
    }
}

OCPJP>javac FlatMapDemo.java 
OCPJP>java FlatMapDemo
======Stream<List<Integer>> test1 = Stream.of(a, b):
1
2
2
5
======Stream<List<?>> test2 = Stream.of(a, b, c):
1
2
2
5
[5, 2]
[0]
======Stream<List<Integer>> test3 = Stream.of(c):
5
2
0
======flat a stream of sentences:
I
like
aplle
I
like
orange
I
dislike
vegi
OCPJP>


It is useful when you want to remove empty elements from a stream or combine a stream of collections.

flatMap() for Optional

A few of the intermediate operations filter, map, flatMap are available for Optional. For example, the following overloaded version of flatMap() operate on an Optional<T>, returns an  Optional<U>. The mapper function has to return an Optional, which is the returned value of flatMap.

According to java doc.

<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper)

   /**
     * If a value is present, apply the provided Optional-bearing
     * mapping function to it, return that result, otherwise return an empty
     * Optional.  This method is similar to map(Function),
     * but the provided mapper is one whose result is already an Optional,
     * and if invoked,  flatMap does not wrap it with an additional
     * Optional.
  **/

public<U> Optional<U> map(Function<? super T, ? extends U> mapper)

/**
     * If a value is present, apply the provided mapping function to it,
     * and if the result is non-null, return an Optional describing the
     * result.  Otherwise return an empty Optional.
     **/



OCPJP>cat ChainingOptionalTest.java 
import java.util.*;
public class ChainingOptionalTest {
    public static void main(String[] args) {
        System.out.println("====a value is present");
        Optional<Integer> optional = Optional.of(10);
        optionalTest(optional);
        System.out.println("====a value is not present");
        optional = Optional.empty();
        optionalTest(optional);
        
    }
    
    private static void optionalTest(Optional<Integer> optional) {
        System.out.println("map(), filter()");
        Optional<String> optional2 = optional.map(n -> "" + n);
        optional2.filter(n -> n.startsWith("1")).ifPresent(System.out::println);
        
        System.out.println("flatMap()'s mapper function returns an Optional, which is then returned unwrapped");
        Optional<Optional<Integer>> nested = Optional.of(optional);
        Optional<String> optional3 = nested.flatMap(n -> Optional.of(n.orElse(-1) + "xxx"));
        optional3.ifPresent(System.out::println);
        
        System.out.println("flatMap()'s mapper function returns an optional, which is then returned unwrapped");
        optional3 = nested.flatMap(n -> Optional.of(n.toString()));
        optional3.ifPresent(System.out::println);
        
        System.out.println("map()'s mapper function returns an object, which is then wrapped with Optional");
        Optional<String> ot = nested.map(n -> n.toString());
        ot.ifPresent(System.out::println);
        
        System.out.println("map()'s mapper function returns an object, which is then wrapped with Optional");
        Optional<Optional<String>> ol = nested.map(n -> Optional.of(n.toString()));
        ol.ifPresent(System.out::println);
    }
}
OCPJP>
OCPJP>
OCPJP>javac ChainingOptionalTest.java 
OCPJP>java ChainingOptionalTest
====a value is present
map(), filter()
10
flatMap()'s mapper function returns an Optional, which is then returned unwrapped
10xxx
flatMap()'s mapper function returns an optional, which is then returned unwrapped
Optional[10]
map()'s mapper function returns an object, which is then wrapped with Optional
Optional[10]
map()'s mapper function returns an object, which is then wrapped with Optional
Optional[Optional[10]]
====a value is not present
map(), filter()
flatMap()'s mapper function returns an Optional, which is then returned unwrapped
-1xxx
flatMap()'s mapper function returns an optional, which is then returned unwrapped
Optional.empty
map()'s mapper function returns an object, which is then wrapped with Optional
Optional.empty
map()'s mapper function returns an object, which is then wrapped with Optional
Optional[Optional.empty]
OCPJP>


Notice the difference of map() and flatMap() on optional.