title: java stream groupingBy + aggregate
body: <pre><code>public class Member {
    private String name;
    private String team;
    private List&lt;String&gt; tasks;
    ...
  }
  </code></pre>
  
  <p>input list like:</p>
  
  <pre><code>member1, team1, [task1]
  member2, team1, [task2]
  member2, team1, [taks3]
  member3, team2, [task4]
  member3, team2, [task5, task6]
  </code></pre>
  
  <p>Try to group by team and aggregate the tasks for each member together, how to write the stream? The expected result is <code>Map&lt;String, List&lt;Member&gt;&gt;</code> like:</p>
  
  <pre><code>team1: [
    member1: [task1]
    member2: [task2, task3]
  ]
  team2: [
    member3: [task4, task5, task6]
  ]
  </code></pre>
  
  <p>grouping by team is easy. The challenge is how to aggregate the tasks for each different member and still maintain the result as `Map></p>
  
  <p><strong>UPDATE:</strong> This is the best I can do, but it's 2 steps. Can anyone merge these to one?</p>
  
  <pre><code>public class Test {
  public static void main(String[] args) {
      Member m1 = new Member("member1", "team1", task("task1"));
      Member m2 = new Member("member2", "team1", task("task2"));
      Member m3 = new Member("member2", "team1", task("task3"));
      Member m4 = new Member("member3", "team2", task("task4"));
      Member m5 = new Member("member3", "team2", task("task5"));
  
      List&lt;Member&gt; list = Arrays.asList(m1, m2, m3, m4, m5);
  
      long start = System.currentTimeMillis();
  
      Map&lt;String, Map&lt;String, Optional&lt;Member&gt;&gt;&gt; result = list.stream()
              .collect(Collectors.groupingBy(Member::getTeam,
                      Collectors.groupingBy(Member::getName, Collectors.reducing(
                              (member1, member2) -&gt; {
                                  member1.getTasks().addAll(member2.getTasks());
                                  return member1;
                              }
                      ))));
      Map&lt;String, List&lt;Member&gt;&gt; result2 = result.entrySet().stream()
              .collect(Collectors.toMap(entry -&gt; entry.getKey(),
                      entry -&gt; entry.getValue().values().stream()
                              .map(e -&gt; e.get()).collect(Collectors.toList())));
  
      result2.entrySet().stream().forEach(System.out::println);
  
      long end = System.currentTimeMillis();
      System.out.println("Total:" + (end - start) + "ms");
  }
  
  private static List&lt;String&gt; task(String... tasks) {
      List&lt;String&gt; list = new ArrayList&lt;&gt;();
      Collections.addAll(list, tasks);
      return list;
  }
  </code></pre>
  
  <p>}</p>