javajava-streamstreamex

Java stream and groupping: put object to multiple groups


I don't think, that it's called "groupping" but I need to achive the following: I have class

class Person {
   String name;
   Set<String> groups;
}

I have some persons:

  1. Father => {"Worker", "Men"}
  2. Mother => {"Woman"}
  3. Son => {"Student","Men"}
  4. Daughter => {"Student","Woman"}

So, every person can be part of multiple categories. And I want to get the following mapping:

"Worker" => {Father}
"Men" => {Father, Son}
"Student" => {Son, Daughter}
"Woman" => {Mother, Daughter}

Now I can do this with manual iterating over every person and putting them to Map<String,List<Person>>

I'm trying to find a more elegant wat to do it with streams (or StreamEx) oneliner, like:

List<Persons> family= ...;
Map<String,List<Person>> groupped = family.stream().groupByMultipleAttributes(Person::getGroups)

Solution

  • You can generate all the associated pairs of groups and Persons, and then collect them with groupingBy into a Map:

    Map<String,List<Person>> groups =
        family.stream()
              .flatMap(p -> p.getGroups()
                             .stream()
                             .map(g -> new SimpleEntry<>(g,p)))
              .collect(Collectors.groupingBy(Map.Entry::getKey,
                                             Collectors.mapping(Map.Entry::getValue,
                                                                Collectors.toList())));