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

      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

    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

      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.

      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

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

Last updated