# Flatmap

* is applicable for anything that is a “container of something”
  * Stream and CompletableFuture
* Combination of mapping then flattening
* The idea for map
  *   take all elements of a stream or collection and apply a function to

      ```java
      Stream.of(1, 2, 3, 4)
      .map(x -> x * 2)
      .collect(Collectors.toList())
      // -> [2, 4, 6, 8]
      ```
*   Applying map to create a list of lists

    ```java
    Stream.of(1, 2, 3, 4)
      .map(x -> Stream.of(-x, x, x + 1))
      .collect(Collectors.toList())
    /*
    [java.util.stream.ReferencePipeline$Head@3532ec19,
    java.util.stream.ReferencePipeline$Head@68c4039c,
    java.util.stream.ReferencePipeline$Head@ae45eb6,
    java.util.stream.ReferencePipeline$Head@59f99ea]
    */
    ```

    * For every singular element, we’re creating a plural. If you perform a map with a plural
    *   Instead use flatmap

        ```java
        Stream.of(1, 2, 3, 4)
         .flatMap(x -> Stream.of(-x, x, x+1))
         .collect(Collectors.toList())
        // [-1, 1, 2, -2, 2, 3, -3, 3, 4, -4, 4, 5]
        ```
* Example
  *   We are given only a Stream and our goal is to determine all the salaries of all employees, including Managers and their Employees.

      ```java
      class Employee {
      private String firstName, lastName;
      private Integer yearlySalary;
      // getters, setters, toString
      }
      class Manager extends Employee {
      private List<Employee> employeeList;
      // getters, setters, toString
      }
      ```
  * Instead of using forEach and start digging through those salaries.
    * **This, unfortunately, would model our code to the structure of the data and would cause needless complexity**
  *   Use flatmap

      ```java
      List.of(manager1, manager2).stream()
      .flatMap(m ->
        Stream.concat(m.getEmployeeList().stream(), Stream.of(m)))
      .distinct()
      .mapToInt(Employee::getYearlySalary)
      ```
