Group by a Collection attribute using Java Streams

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
9
down vote

favorite
1












I have an object that contains a Collection of strings, let's say the languages that a person speaks.



public class Person 
private String name;
private int age;
private List<String> languagesSpoken;

// ...



Now, creating some instances like this...



Person p1 = new Person("Bob", 21, Arrays.asList("English", "French", "German"));
Person p2 = new Person("Alice", 33, Arrays.asList("English", "Chinese", Spanish"));
Person p3 = new Person("Joe", 43, Arrays.asList("English", "Dutch", "Spanish", "German"));

//put them in list
List<Person> people = Arrays.asList(p1,p2,p3);


... what I want to have is a Map<String, List<Person>>, for every language listing the persons that speak the language:



["English" -> [Bob object, Alice object, Joe object],
"German" -> [Bob object, Joe object],
etc. ]


Of course this can be programmed easily in an imperative way, but how to do it the functional way with Java Streams? I have tried something like people.stream.collect(groupingBy(Person::getLanguagesSpoken)) but that of course gives me a Map<List<String>, List<Person>>. All the examples I could find, are using groupingBy on Primitives or Strings.










share|improve this question

























    up vote
    9
    down vote

    favorite
    1












    I have an object that contains a Collection of strings, let's say the languages that a person speaks.



    public class Person 
    private String name;
    private int age;
    private List<String> languagesSpoken;

    // ...



    Now, creating some instances like this...



    Person p1 = new Person("Bob", 21, Arrays.asList("English", "French", "German"));
    Person p2 = new Person("Alice", 33, Arrays.asList("English", "Chinese", Spanish"));
    Person p3 = new Person("Joe", 43, Arrays.asList("English", "Dutch", "Spanish", "German"));

    //put them in list
    List<Person> people = Arrays.asList(p1,p2,p3);


    ... what I want to have is a Map<String, List<Person>>, for every language listing the persons that speak the language:



    ["English" -> [Bob object, Alice object, Joe object],
    "German" -> [Bob object, Joe object],
    etc. ]


    Of course this can be programmed easily in an imperative way, but how to do it the functional way with Java Streams? I have tried something like people.stream.collect(groupingBy(Person::getLanguagesSpoken)) but that of course gives me a Map<List<String>, List<Person>>. All the examples I could find, are using groupingBy on Primitives or Strings.










    share|improve this question























      up vote
      9
      down vote

      favorite
      1









      up vote
      9
      down vote

      favorite
      1






      1





      I have an object that contains a Collection of strings, let's say the languages that a person speaks.



      public class Person 
      private String name;
      private int age;
      private List<String> languagesSpoken;

      // ...



      Now, creating some instances like this...



      Person p1 = new Person("Bob", 21, Arrays.asList("English", "French", "German"));
      Person p2 = new Person("Alice", 33, Arrays.asList("English", "Chinese", Spanish"));
      Person p3 = new Person("Joe", 43, Arrays.asList("English", "Dutch", "Spanish", "German"));

      //put them in list
      List<Person> people = Arrays.asList(p1,p2,p3);


      ... what I want to have is a Map<String, List<Person>>, for every language listing the persons that speak the language:



      ["English" -> [Bob object, Alice object, Joe object],
      "German" -> [Bob object, Joe object],
      etc. ]


      Of course this can be programmed easily in an imperative way, but how to do it the functional way with Java Streams? I have tried something like people.stream.collect(groupingBy(Person::getLanguagesSpoken)) but that of course gives me a Map<List<String>, List<Person>>. All the examples I could find, are using groupingBy on Primitives or Strings.










      share|improve this question













      I have an object that contains a Collection of strings, let's say the languages that a person speaks.



      public class Person 
      private String name;
      private int age;
      private List<String> languagesSpoken;

      // ...



      Now, creating some instances like this...



      Person p1 = new Person("Bob", 21, Arrays.asList("English", "French", "German"));
      Person p2 = new Person("Alice", 33, Arrays.asList("English", "Chinese", Spanish"));
      Person p3 = new Person("Joe", 43, Arrays.asList("English", "Dutch", "Spanish", "German"));

      //put them in list
      List<Person> people = Arrays.asList(p1,p2,p3);


      ... what I want to have is a Map<String, List<Person>>, for every language listing the persons that speak the language:



      ["English" -> [Bob object, Alice object, Joe object],
      "German" -> [Bob object, Joe object],
      etc. ]


      Of course this can be programmed easily in an imperative way, but how to do it the functional way with Java Streams? I have tried something like people.stream.collect(groupingBy(Person::getLanguagesSpoken)) but that of course gives me a Map<List<String>, List<Person>>. All the examples I could find, are using groupingBy on Primitives or Strings.







      java java-8 java-stream






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked 24 mins ago









      user3579358

      6313




      6313






















          1 Answer
          1






          active

          oldest

          votes

















          up vote
          11
          down vote













          You can break the Person instances into pairs of language and Person (using flatMap) and then group them as required:



          Map<String, List<Person>> langPersons =
          people.stream()
          .flatMap(p -> p.getLanguagesSpoken()
          .stream()
          .map(l -> new SimpleEntry<>(l,p)))
          .collect(Collectors.groupingBy(Map.Entry::getKey,
          Collectors.mapping(Map.Entry::getValue,
          Collectors.toList())));





          share|improve this answer






















            Your Answer





            StackExchange.ifUsing("editor", function ()
            StackExchange.using("externalEditor", function ()
            StackExchange.using("snippets", function ()
            StackExchange.snippets.init();
            );
            );
            , "code-snippets");

            StackExchange.ready(function()
            var channelOptions =
            tags: "".split(" "),
            id: "1"
            ;
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function()
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled)
            StackExchange.using("snippets", function()
            createEditor();
            );

            else
            createEditor();

            );

            function createEditor()
            StackExchange.prepareEditor(
            heartbeatType: 'answer',
            convertImagesToLinks: true,
            noModals: false,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            );



            );













             

            draft saved


            draft discarded


















            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52984816%2fgroup-by-a-collection-attribute-using-java-streams%23new-answer', 'question_page');

            );

            Post as a guest






























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes








            up vote
            11
            down vote













            You can break the Person instances into pairs of language and Person (using flatMap) and then group them as required:



            Map<String, List<Person>> langPersons =
            people.stream()
            .flatMap(p -> p.getLanguagesSpoken()
            .stream()
            .map(l -> new SimpleEntry<>(l,p)))
            .collect(Collectors.groupingBy(Map.Entry::getKey,
            Collectors.mapping(Map.Entry::getValue,
            Collectors.toList())));





            share|improve this answer


























              up vote
              11
              down vote













              You can break the Person instances into pairs of language and Person (using flatMap) and then group them as required:



              Map<String, List<Person>> langPersons =
              people.stream()
              .flatMap(p -> p.getLanguagesSpoken()
              .stream()
              .map(l -> new SimpleEntry<>(l,p)))
              .collect(Collectors.groupingBy(Map.Entry::getKey,
              Collectors.mapping(Map.Entry::getValue,
              Collectors.toList())));





              share|improve this answer
























                up vote
                11
                down vote










                up vote
                11
                down vote









                You can break the Person instances into pairs of language and Person (using flatMap) and then group them as required:



                Map<String, List<Person>> langPersons =
                people.stream()
                .flatMap(p -> p.getLanguagesSpoken()
                .stream()
                .map(l -> new SimpleEntry<>(l,p)))
                .collect(Collectors.groupingBy(Map.Entry::getKey,
                Collectors.mapping(Map.Entry::getValue,
                Collectors.toList())));





                share|improve this answer














                You can break the Person instances into pairs of language and Person (using flatMap) and then group them as required:



                Map<String, List<Person>> langPersons =
                people.stream()
                .flatMap(p -> p.getLanguagesSpoken()
                .stream()
                .map(l -> new SimpleEntry<>(l,p)))
                .collect(Collectors.groupingBy(Map.Entry::getKey,
                Collectors.mapping(Map.Entry::getValue,
                Collectors.toList())));






                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited 16 mins ago

























                answered 19 mins ago









                Eran

                268k35416503




                268k35416503



























                     

                    draft saved


                    draft discarded















































                     


                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function ()
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52984816%2fgroup-by-a-collection-attribute-using-java-streams%23new-answer', 'question_page');

                    );

                    Post as a guest













































































                    Comments

                    Popular posts from this blog

                    What does second last employer means? [closed]

                    List of Gilmore Girls characters

                    One-line joke