Stream groupingBy sub type

Viewed 238

I've 2 entites:

class Parent {
    Integer id;
    List<Child> children;
}

class Child {

    Integer id;
    Parent parent;
}

In my DB query I'm fetching a list of Parents. Now I want to group this list by Child IDs, i.e.

Map<Integer, List<Parent>> myMap;

Using Java 8's grouping by how can I do this?

Right now I'm using resultList.stream().collect(groupingBy(Parent::getChildren)), but this creates Map<Set<Child>, List<Parent>>, which is not what I'm looking for.

2 Answers

Perhaps you may find flatMap useful here:

Map<Integer, List<Parent>> childMap = 
    resultList.stream()
              .flatMap(Parent::getChildren)
              .collect(groupingBy(Child::getId, Collectors.mapping(Child::getParent,                                        
                                                    Collectors.toList())));

Use flatMap to get the children. Then create map entry for child id and parent. Then grouping by child id the map entry list and collect the map entry groups value as list.

Map<Integer, List<Parent>> myMap = 
      resultList
        .stream()
        .flatMap(e -> e.getChildren().stream()
                       .map(a -> new SimpleEntry<Integer,Parent>(a.getId(), e)))
        .collect(Collectors.groupingBy(Map.Entry::getKey,
                                       Collectors.mapping(Map.Entry::getValue,
                                                          Collectors.toList())));

Or more simplified using the constructor of Child

Map<Integer, List<Parent>> myMap = 
      resultList
        .stream()
        .flatMap(e -> e.getChildren().stream()
                       .map(a -> new Child(a.getId(), e)))
        .collect(Collectors.groupingBy(Child::getId, Collectors.mapping(Child::getParent,
                                                          Collectors.toList())));

And if for every parent's every child has parent data available then @cs95 solution is better.

Related