Collect results of a map operation in a Map using Collectors.toMap or groupingByHow do I efficiently iterate over each entry in a Java Map?Sort a Map<Key, Value> by valuesA Java collection of value pairs? (tuples?)Why is subtracting these two times (in 1927) giving a strange result?Why don't Java's +=, -=, *=, /= compound assignment operators require casting?:: (double colon) operator in Java 8Java 8 List<V> into Map<K, V>Java 8 NullPointerException in Collectors.toMapWhat's the difference between map() and flatMap() methods in Java 8?Java 8 Join Map with Collectors.toMap

How to be ready for The Rise of Skywalker?

find ".ts" but not ".d.ts"

To whom does "Madam Speaker" refer during the Trump impeachment debate?

How Do We Add Structurally Sound Faux Stud for a Single Stud TV Mount?

Is it possible to conserve the total kinetic energy of a system, but not its momentum?

Was Jumanji intended to be a co-op game?

Can a weapon be "unsheathable"?

Can this crack in the steel chain-side dropout be welded?

How to Handle Competitive and Blame Culture Within Team

What makes ValueTuple covariant?

Was Greta Thunberg forced to ride on the floor of an overcrowded train?

Why is the OS obfuscation defense against "It's a Unix system!" not widely implemented?

Limit number of matches of find command

In Excel, is there a shortcut to hide a wide range of columns without mouse-dragging?

How are the Van der Waals constants a and b related to each other?

What happens when a photon "dies"?

Should I sign a NDA that holds me liable for legal fees even if I am in the right?

Align vertex preserving the angle

How scammy are cashback sites?

Understanding of big-O massively improved when I began thinking of orders as sets. How to apply the same approach to big-Theta?

Should I take a side in an external player conflict, or let my game die?

Should we stop differentiating between ln and log?

Would it have been possible to re-fuel the planes in the air?

Excel countif doesn't work on range denoted by



Collect results of a map operation in a Map using Collectors.toMap or groupingBy


How do I efficiently iterate over each entry in a Java Map?Sort a Map<Key, Value> by valuesA Java collection of value pairs? (tuples?)Why is subtracting these two times (in 1927) giving a strange result?Why don't Java's +=, -=, *=, /= compound assignment operators require casting?:: (double colon) operator in Java 8Java 8 List<V> into Map<K, V>Java 8 NullPointerException in Collectors.toMapWhat's the difference between map() and flatMap() methods in Java 8?Java 8 Join Map with Collectors.toMap






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty
margin-bottom:0;









8


















I've got a list of type List<A> and with map operation getting a collective list of type List<B> for all A elements merged in one list.



List<A> listofA = [A1, A2, A3, A4, A5, ...]

List<B> listofB = listofA.stream()
.map(a -> repo.getListofB(a))
.flatMap(Collection::stream)
.collect(Collectors.toList());


without flatmap



List<List<B>> listOflistofB = listofA.stream()
.map(a -> repo.getListofB(a))
.collect(Collectors.toList());


I want to collect the results as a map of type Map<A, List<B>> and so far trying with various Collectors.toMap or Collectors.groupingBy options but not able to get the desired result.










share|improve this question






















  • 2





    Do you have repeated A elements in your List<A>?

    – Federico Peralta Schaffner
    Oct 2 at 15:15


















8


















I've got a list of type List<A> and with map operation getting a collective list of type List<B> for all A elements merged in one list.



List<A> listofA = [A1, A2, A3, A4, A5, ...]

List<B> listofB = listofA.stream()
.map(a -> repo.getListofB(a))
.flatMap(Collection::stream)
.collect(Collectors.toList());


without flatmap



List<List<B>> listOflistofB = listofA.stream()
.map(a -> repo.getListofB(a))
.collect(Collectors.toList());


I want to collect the results as a map of type Map<A, List<B>> and so far trying with various Collectors.toMap or Collectors.groupingBy options but not able to get the desired result.










share|improve this question






















  • 2





    Do you have repeated A elements in your List<A>?

    – Federico Peralta Schaffner
    Oct 2 at 15:15














8













8









8


2






I've got a list of type List<A> and with map operation getting a collective list of type List<B> for all A elements merged in one list.



List<A> listofA = [A1, A2, A3, A4, A5, ...]

List<B> listofB = listofA.stream()
.map(a -> repo.getListofB(a))
.flatMap(Collection::stream)
.collect(Collectors.toList());


without flatmap



List<List<B>> listOflistofB = listofA.stream()
.map(a -> repo.getListofB(a))
.collect(Collectors.toList());


I want to collect the results as a map of type Map<A, List<B>> and so far trying with various Collectors.toMap or Collectors.groupingBy options but not able to get the desired result.










share|improve this question
















I've got a list of type List<A> and with map operation getting a collective list of type List<B> for all A elements merged in one list.



List<A> listofA = [A1, A2, A3, A4, A5, ...]

List<B> listofB = listofA.stream()
.map(a -> repo.getListofB(a))
.flatMap(Collection::stream)
.collect(Collectors.toList());


without flatmap



List<List<B>> listOflistofB = listofA.stream()
.map(a -> repo.getListofB(a))
.collect(Collectors.toList());


I want to collect the results as a map of type Map<A, List<B>> and so far trying with various Collectors.toMap or Collectors.groupingBy options but not able to get the desired result.







java lambda java-8 java-stream collectors






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Oct 2 at 16:08









Ravindra Ranwala

15.9k6 gold badges31 silver badges47 bronze badges




15.9k6 gold badges31 silver badges47 bronze badges










asked Oct 2 at 14:44









AmitojAmitoj

2851 silver badge9 bronze badges




2851 silver badge9 bronze badges










  • 2





    Do you have repeated A elements in your List<A>?

    – Federico Peralta Schaffner
    Oct 2 at 15:15













  • 2





    Do you have repeated A elements in your List<A>?

    – Federico Peralta Schaffner
    Oct 2 at 15:15








2




2





Do you have repeated A elements in your List<A>?

– Federico Peralta Schaffner
Oct 2 at 15:15






Do you have repeated A elements in your List<A>?

– Federico Peralta Schaffner
Oct 2 at 15:15













4 Answers
4






active

oldest

votes


















8



















You can use the toMap collector with a bounded method reference to get what you need. Also notice that this solution assumes you don't have repeated A instances in your source container. If that precondition holds this solution would give you the desired result. Here's how it looks.



Map<A, Collection<B>> resultMap = listofA.stream()
.collect(Collectors.toMap(Function.identity(), repo::getListofB);


If you have duplicate A elements, then you have to use this merge function in addition to what is given above. The merge function deals with key conflicts if any.



Map<A, Collection<B>> resultMap = listofA.stream()
.collect(Collectors.toMap(Function.identity(), repo::getListofB,
(a, b) ->
a.addAll(b);
return a;
));


And here's a much more succinct Java9 approach which uses the flatMapping collector to handle repeated A elements.



Map<A, List<B>> aToBmap = listofA.stream()
.collect(Collectors.groupingBy(Function.identity(),
Collectors.flatMapping(a -> getListofB(a).stream(),
Collectors.toList())));





share|improve this answer






















  • 2





    Hey, nice you've added how to handle duplicates! I was adding an answer with that, I will let it because I think it complements yours, cheers!

    – Federico Peralta Schaffner
    Oct 2 at 15:34







  • 2





    Yes, your comment was helpful. Good catch !

    – Ravindra Ranwala
    Oct 2 at 15:35


















3



















It would be straight forward,



listofA.stream().collect(toMap(Function.identity(), a -> getListofB(a)));





share|improve this answer
































    2



















    To collect a Map where keys are the A objects unchanged, and the values are the list of corresponding B objects, you can replace the toList() collector by the following collector :



    toMap(Function.identity(), a -> repo.getListOfB(a))


    The first argument defines how to compute the key from the original object : identity() takes the original object of the stream unchanged.



    The second argument defines how the value is computed, so here it just consists of a call to your method that transforms a A to a list of B.



    Since the repo method takes only one parameter, you can also improve clarity by replacing the lambda with a method reference :



    toMap(Function.identity(), repo::getListOfB)





    share|improve this answer



























    • Thanks @kgautron, your answer is correct and clearly explained. I accepted the other answer because I saw it first.

      – Amitoj
      Oct 2 at 15:10


















    2



















    In this answer, I'm showing what happens if you have repeated A elements in your List<A> listofA list.



    Actually, if there were duplicates in listofA, the following code would throw an IllegalStateException:



    Map<A, Collection<B>> resultMap = listofA.stream()
    .collect(Collectors.toMap(
    Function.identity(),
    repo::getListofB);


    The exception might be thrown because Collectors.toMap doesn't know how to merge values when there is a collision in the keys (i.e. when the key mapper function returns duplicates, as it would be the case for Function.identity() if there were repeated elements in the listofA list).



    This is clearly stated in the docs:




    If the mapped keys contains duplicates (according to Object.equals(Object)), an IllegalStateException is thrown when the collection operation is performed. If the mapped keys may have duplicates, use toMap(Function, Function, BinaryOperator) instead.




    The docs also give us the solution: in case there are repeated elements, we need to provide a way to merge values. Here's one such way:



    Map<A, Collection<B>> resultMap = listofA.stream()
    .collect(Collectors.toMap(
    Function.identity(),
    a -> new ArrayList<>(repo.getListofB(a)),
    (left, right) ->
    left.addAll(right);
    return left;
    );


    This uses the overloaded version of Collectors.toMap that accepts a merge function as its third argument. Within the merge function, Collection.addAll is being used to add the B elements of each repeated A element into a unqiue list for each A.



    In the value mapper function, a new ArrayList is created, so that the original List<B> of each A is not mutated. Also, as we're creating an Arraylist, we know in advance that it can be mutated (i.e. we can add elements to it later, in case there are duplicates in listofA).






    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',
      autoActivateHeartbeat: false,
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader:
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/4.0/"u003ecc by-sa 4.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      ,
      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%2f58203884%2fcollect-results-of-a-map-operation-in-a-map-using-collectors-tomap-or-groupingby%23new-answer', 'question_page');

      );

      Post as a guest















      Required, but never shown


























      4 Answers
      4






      active

      oldest

      votes








      4 Answers
      4






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      8



















      You can use the toMap collector with a bounded method reference to get what you need. Also notice that this solution assumes you don't have repeated A instances in your source container. If that precondition holds this solution would give you the desired result. Here's how it looks.



      Map<A, Collection<B>> resultMap = listofA.stream()
      .collect(Collectors.toMap(Function.identity(), repo::getListofB);


      If you have duplicate A elements, then you have to use this merge function in addition to what is given above. The merge function deals with key conflicts if any.



      Map<A, Collection<B>> resultMap = listofA.stream()
      .collect(Collectors.toMap(Function.identity(), repo::getListofB,
      (a, b) ->
      a.addAll(b);
      return a;
      ));


      And here's a much more succinct Java9 approach which uses the flatMapping collector to handle repeated A elements.



      Map<A, List<B>> aToBmap = listofA.stream()
      .collect(Collectors.groupingBy(Function.identity(),
      Collectors.flatMapping(a -> getListofB(a).stream(),
      Collectors.toList())));





      share|improve this answer






















      • 2





        Hey, nice you've added how to handle duplicates! I was adding an answer with that, I will let it because I think it complements yours, cheers!

        – Federico Peralta Schaffner
        Oct 2 at 15:34







      • 2





        Yes, your comment was helpful. Good catch !

        – Ravindra Ranwala
        Oct 2 at 15:35















      8



















      You can use the toMap collector with a bounded method reference to get what you need. Also notice that this solution assumes you don't have repeated A instances in your source container. If that precondition holds this solution would give you the desired result. Here's how it looks.



      Map<A, Collection<B>> resultMap = listofA.stream()
      .collect(Collectors.toMap(Function.identity(), repo::getListofB);


      If you have duplicate A elements, then you have to use this merge function in addition to what is given above. The merge function deals with key conflicts if any.



      Map<A, Collection<B>> resultMap = listofA.stream()
      .collect(Collectors.toMap(Function.identity(), repo::getListofB,
      (a, b) ->
      a.addAll(b);
      return a;
      ));


      And here's a much more succinct Java9 approach which uses the flatMapping collector to handle repeated A elements.



      Map<A, List<B>> aToBmap = listofA.stream()
      .collect(Collectors.groupingBy(Function.identity(),
      Collectors.flatMapping(a -> getListofB(a).stream(),
      Collectors.toList())));





      share|improve this answer






















      • 2





        Hey, nice you've added how to handle duplicates! I was adding an answer with that, I will let it because I think it complements yours, cheers!

        – Federico Peralta Schaffner
        Oct 2 at 15:34







      • 2





        Yes, your comment was helpful. Good catch !

        – Ravindra Ranwala
        Oct 2 at 15:35













      8















      8











      8









      You can use the toMap collector with a bounded method reference to get what you need. Also notice that this solution assumes you don't have repeated A instances in your source container. If that precondition holds this solution would give you the desired result. Here's how it looks.



      Map<A, Collection<B>> resultMap = listofA.stream()
      .collect(Collectors.toMap(Function.identity(), repo::getListofB);


      If you have duplicate A elements, then you have to use this merge function in addition to what is given above. The merge function deals with key conflicts if any.



      Map<A, Collection<B>> resultMap = listofA.stream()
      .collect(Collectors.toMap(Function.identity(), repo::getListofB,
      (a, b) ->
      a.addAll(b);
      return a;
      ));


      And here's a much more succinct Java9 approach which uses the flatMapping collector to handle repeated A elements.



      Map<A, List<B>> aToBmap = listofA.stream()
      .collect(Collectors.groupingBy(Function.identity(),
      Collectors.flatMapping(a -> getListofB(a).stream(),
      Collectors.toList())));





      share|improve this answer
















      You can use the toMap collector with a bounded method reference to get what you need. Also notice that this solution assumes you don't have repeated A instances in your source container. If that precondition holds this solution would give you the desired result. Here's how it looks.



      Map<A, Collection<B>> resultMap = listofA.stream()
      .collect(Collectors.toMap(Function.identity(), repo::getListofB);


      If you have duplicate A elements, then you have to use this merge function in addition to what is given above. The merge function deals with key conflicts if any.



      Map<A, Collection<B>> resultMap = listofA.stream()
      .collect(Collectors.toMap(Function.identity(), repo::getListofB,
      (a, b) ->
      a.addAll(b);
      return a;
      ));


      And here's a much more succinct Java9 approach which uses the flatMapping collector to handle repeated A elements.



      Map<A, List<B>> aToBmap = listofA.stream()
      .collect(Collectors.groupingBy(Function.identity(),
      Collectors.flatMapping(a -> getListofB(a).stream(),
      Collectors.toList())));






      share|improve this answer















      share|improve this answer




      share|improve this answer








      edited Oct 5 at 1:57

























      answered Oct 2 at 14:58









      Ravindra RanwalaRavindra Ranwala

      15.9k6 gold badges31 silver badges47 bronze badges




      15.9k6 gold badges31 silver badges47 bronze badges










      • 2





        Hey, nice you've added how to handle duplicates! I was adding an answer with that, I will let it because I think it complements yours, cheers!

        – Federico Peralta Schaffner
        Oct 2 at 15:34







      • 2





        Yes, your comment was helpful. Good catch !

        – Ravindra Ranwala
        Oct 2 at 15:35












      • 2





        Hey, nice you've added how to handle duplicates! I was adding an answer with that, I will let it because I think it complements yours, cheers!

        – Federico Peralta Schaffner
        Oct 2 at 15:34







      • 2





        Yes, your comment was helpful. Good catch !

        – Ravindra Ranwala
        Oct 2 at 15:35







      2




      2





      Hey, nice you've added how to handle duplicates! I was adding an answer with that, I will let it because I think it complements yours, cheers!

      – Federico Peralta Schaffner
      Oct 2 at 15:34






      Hey, nice you've added how to handle duplicates! I was adding an answer with that, I will let it because I think it complements yours, cheers!

      – Federico Peralta Schaffner
      Oct 2 at 15:34





      2




      2





      Yes, your comment was helpful. Good catch !

      – Ravindra Ranwala
      Oct 2 at 15:35





      Yes, your comment was helpful. Good catch !

      – Ravindra Ranwala
      Oct 2 at 15:35













      3



















      It would be straight forward,



      listofA.stream().collect(toMap(Function.identity(), a -> getListofB(a)));





      share|improve this answer





























        3



















        It would be straight forward,



        listofA.stream().collect(toMap(Function.identity(), a -> getListofB(a)));





        share|improve this answer



























          3















          3











          3









          It would be straight forward,



          listofA.stream().collect(toMap(Function.identity(), a -> getListofB(a)));





          share|improve this answer














          It would be straight forward,



          listofA.stream().collect(toMap(Function.identity(), a -> getListofB(a)));






          share|improve this answer













          share|improve this answer




          share|improve this answer










          answered Oct 2 at 14:59









          Code_ModeCode_Mode

          3,66215 silver badges25 bronze badges




          3,66215 silver badges25 bronze badges
























              2



















              To collect a Map where keys are the A objects unchanged, and the values are the list of corresponding B objects, you can replace the toList() collector by the following collector :



              toMap(Function.identity(), a -> repo.getListOfB(a))


              The first argument defines how to compute the key from the original object : identity() takes the original object of the stream unchanged.



              The second argument defines how the value is computed, so here it just consists of a call to your method that transforms a A to a list of B.



              Since the repo method takes only one parameter, you can also improve clarity by replacing the lambda with a method reference :



              toMap(Function.identity(), repo::getListOfB)





              share|improve this answer



























              • Thanks @kgautron, your answer is correct and clearly explained. I accepted the other answer because I saw it first.

                – Amitoj
                Oct 2 at 15:10















              2



















              To collect a Map where keys are the A objects unchanged, and the values are the list of corresponding B objects, you can replace the toList() collector by the following collector :



              toMap(Function.identity(), a -> repo.getListOfB(a))


              The first argument defines how to compute the key from the original object : identity() takes the original object of the stream unchanged.



              The second argument defines how the value is computed, so here it just consists of a call to your method that transforms a A to a list of B.



              Since the repo method takes only one parameter, you can also improve clarity by replacing the lambda with a method reference :



              toMap(Function.identity(), repo::getListOfB)





              share|improve this answer



























              • Thanks @kgautron, your answer is correct and clearly explained. I accepted the other answer because I saw it first.

                – Amitoj
                Oct 2 at 15:10













              2















              2











              2









              To collect a Map where keys are the A objects unchanged, and the values are the list of corresponding B objects, you can replace the toList() collector by the following collector :



              toMap(Function.identity(), a -> repo.getListOfB(a))


              The first argument defines how to compute the key from the original object : identity() takes the original object of the stream unchanged.



              The second argument defines how the value is computed, so here it just consists of a call to your method that transforms a A to a list of B.



              Since the repo method takes only one parameter, you can also improve clarity by replacing the lambda with a method reference :



              toMap(Function.identity(), repo::getListOfB)





              share|improve this answer
















              To collect a Map where keys are the A objects unchanged, and the values are the list of corresponding B objects, you can replace the toList() collector by the following collector :



              toMap(Function.identity(), a -> repo.getListOfB(a))


              The first argument defines how to compute the key from the original object : identity() takes the original object of the stream unchanged.



              The second argument defines how the value is computed, so here it just consists of a call to your method that transforms a A to a list of B.



              Since the repo method takes only one parameter, you can also improve clarity by replacing the lambda with a method reference :



              toMap(Function.identity(), repo::getListOfB)






              share|improve this answer















              share|improve this answer




              share|improve this answer








              edited Oct 2 at 15:10

























              answered Oct 2 at 14:59









              kgautronkgautron

              6,5717 gold badges34 silver badges57 bronze badges




              6,5717 gold badges34 silver badges57 bronze badges















              • Thanks @kgautron, your answer is correct and clearly explained. I accepted the other answer because I saw it first.

                – Amitoj
                Oct 2 at 15:10

















              • Thanks @kgautron, your answer is correct and clearly explained. I accepted the other answer because I saw it first.

                – Amitoj
                Oct 2 at 15:10
















              Thanks @kgautron, your answer is correct and clearly explained. I accepted the other answer because I saw it first.

              – Amitoj
              Oct 2 at 15:10





              Thanks @kgautron, your answer is correct and clearly explained. I accepted the other answer because I saw it first.

              – Amitoj
              Oct 2 at 15:10











              2



















              In this answer, I'm showing what happens if you have repeated A elements in your List<A> listofA list.



              Actually, if there were duplicates in listofA, the following code would throw an IllegalStateException:



              Map<A, Collection<B>> resultMap = listofA.stream()
              .collect(Collectors.toMap(
              Function.identity(),
              repo::getListofB);


              The exception might be thrown because Collectors.toMap doesn't know how to merge values when there is a collision in the keys (i.e. when the key mapper function returns duplicates, as it would be the case for Function.identity() if there were repeated elements in the listofA list).



              This is clearly stated in the docs:




              If the mapped keys contains duplicates (according to Object.equals(Object)), an IllegalStateException is thrown when the collection operation is performed. If the mapped keys may have duplicates, use toMap(Function, Function, BinaryOperator) instead.




              The docs also give us the solution: in case there are repeated elements, we need to provide a way to merge values. Here's one such way:



              Map<A, Collection<B>> resultMap = listofA.stream()
              .collect(Collectors.toMap(
              Function.identity(),
              a -> new ArrayList<>(repo.getListofB(a)),
              (left, right) ->
              left.addAll(right);
              return left;
              );


              This uses the overloaded version of Collectors.toMap that accepts a merge function as its third argument. Within the merge function, Collection.addAll is being used to add the B elements of each repeated A element into a unqiue list for each A.



              In the value mapper function, a new ArrayList is created, so that the original List<B> of each A is not mutated. Also, as we're creating an Arraylist, we know in advance that it can be mutated (i.e. we can add elements to it later, in case there are duplicates in listofA).






              share|improve this answer





























                2



















                In this answer, I'm showing what happens if you have repeated A elements in your List<A> listofA list.



                Actually, if there were duplicates in listofA, the following code would throw an IllegalStateException:



                Map<A, Collection<B>> resultMap = listofA.stream()
                .collect(Collectors.toMap(
                Function.identity(),
                repo::getListofB);


                The exception might be thrown because Collectors.toMap doesn't know how to merge values when there is a collision in the keys (i.e. when the key mapper function returns duplicates, as it would be the case for Function.identity() if there were repeated elements in the listofA list).



                This is clearly stated in the docs:




                If the mapped keys contains duplicates (according to Object.equals(Object)), an IllegalStateException is thrown when the collection operation is performed. If the mapped keys may have duplicates, use toMap(Function, Function, BinaryOperator) instead.




                The docs also give us the solution: in case there are repeated elements, we need to provide a way to merge values. Here's one such way:



                Map<A, Collection<B>> resultMap = listofA.stream()
                .collect(Collectors.toMap(
                Function.identity(),
                a -> new ArrayList<>(repo.getListofB(a)),
                (left, right) ->
                left.addAll(right);
                return left;
                );


                This uses the overloaded version of Collectors.toMap that accepts a merge function as its third argument. Within the merge function, Collection.addAll is being used to add the B elements of each repeated A element into a unqiue list for each A.



                In the value mapper function, a new ArrayList is created, so that the original List<B> of each A is not mutated. Also, as we're creating an Arraylist, we know in advance that it can be mutated (i.e. we can add elements to it later, in case there are duplicates in listofA).






                share|improve this answer



























                  2















                  2











                  2









                  In this answer, I'm showing what happens if you have repeated A elements in your List<A> listofA list.



                  Actually, if there were duplicates in listofA, the following code would throw an IllegalStateException:



                  Map<A, Collection<B>> resultMap = listofA.stream()
                  .collect(Collectors.toMap(
                  Function.identity(),
                  repo::getListofB);


                  The exception might be thrown because Collectors.toMap doesn't know how to merge values when there is a collision in the keys (i.e. when the key mapper function returns duplicates, as it would be the case for Function.identity() if there were repeated elements in the listofA list).



                  This is clearly stated in the docs:




                  If the mapped keys contains duplicates (according to Object.equals(Object)), an IllegalStateException is thrown when the collection operation is performed. If the mapped keys may have duplicates, use toMap(Function, Function, BinaryOperator) instead.




                  The docs also give us the solution: in case there are repeated elements, we need to provide a way to merge values. Here's one such way:



                  Map<A, Collection<B>> resultMap = listofA.stream()
                  .collect(Collectors.toMap(
                  Function.identity(),
                  a -> new ArrayList<>(repo.getListofB(a)),
                  (left, right) ->
                  left.addAll(right);
                  return left;
                  );


                  This uses the overloaded version of Collectors.toMap that accepts a merge function as its third argument. Within the merge function, Collection.addAll is being used to add the B elements of each repeated A element into a unqiue list for each A.



                  In the value mapper function, a new ArrayList is created, so that the original List<B> of each A is not mutated. Also, as we're creating an Arraylist, we know in advance that it can be mutated (i.e. we can add elements to it later, in case there are duplicates in listofA).






                  share|improve this answer














                  In this answer, I'm showing what happens if you have repeated A elements in your List<A> listofA list.



                  Actually, if there were duplicates in listofA, the following code would throw an IllegalStateException:



                  Map<A, Collection<B>> resultMap = listofA.stream()
                  .collect(Collectors.toMap(
                  Function.identity(),
                  repo::getListofB);


                  The exception might be thrown because Collectors.toMap doesn't know how to merge values when there is a collision in the keys (i.e. when the key mapper function returns duplicates, as it would be the case for Function.identity() if there were repeated elements in the listofA list).



                  This is clearly stated in the docs:




                  If the mapped keys contains duplicates (according to Object.equals(Object)), an IllegalStateException is thrown when the collection operation is performed. If the mapped keys may have duplicates, use toMap(Function, Function, BinaryOperator) instead.




                  The docs also give us the solution: in case there are repeated elements, we need to provide a way to merge values. Here's one such way:



                  Map<A, Collection<B>> resultMap = listofA.stream()
                  .collect(Collectors.toMap(
                  Function.identity(),
                  a -> new ArrayList<>(repo.getListofB(a)),
                  (left, right) ->
                  left.addAll(right);
                  return left;
                  );


                  This uses the overloaded version of Collectors.toMap that accepts a merge function as its third argument. Within the merge function, Collection.addAll is being used to add the B elements of each repeated A element into a unqiue list for each A.



                  In the value mapper function, a new ArrayList is created, so that the original List<B> of each A is not mutated. Also, as we're creating an Arraylist, we know in advance that it can be mutated (i.e. we can add elements to it later, in case there are duplicates in listofA).







                  share|improve this answer













                  share|improve this answer




                  share|improve this answer










                  answered Oct 2 at 15:38









                  Federico Peralta SchaffnerFederico Peralta Schaffner

                  26.2k5 gold badges42 silver badges84 bronze badges




                  26.2k5 gold badges42 silver badges84 bronze badges































                      draft saved

                      draft discarded















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid


                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.

                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function ()
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f58203884%2fcollect-results-of-a-map-operation-in-a-map-using-collectors-tomap-or-groupingby%23new-answer', 'question_page');

                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown









                      Popular posts from this blog

                      Distance measures on a map of a game The 2019 Stack Overflow Developer Survey Results Are Inmin distance in a graphShortest distance path on contour plotHow to plot a tilted map?Finding points outside of a diskDelaunay link distanceAnnulus from GeoDisks: drawing a ring on a mapNegative Correlation DistanceFind distance along a path (GPS coordinates)Finding position at given distance in a GeoPathMathematics behind distance estimation using camera

                      How to get a smooth, uniform ParametricPlot of a 2D Region?How to plot a complicated Region?How to exclude a region from ParametricPlotHow discretize a region placing vertices on a specific non-uniform gridHow to transform a Plot or a ParametricPlot into a RegionHow can I get a smooth plot of a bounded region?Smooth ParametricPlot3D with RegionFunction?Smooth border of a region ParametricPlotSmooth region boundarySmooth region plot from list of pointsGet minimum y of a certain x in a region

                      Genealogie vun de Merowenger Vum Merowech bis zum Chilperich I. | Navigatiounsmenü