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

Can one use mythology to study the history of a region?

how do you value what your leisure time is worth?

How does Lightning Network over TOR work?

What is this dial on my old SLR for?

A demigod among men

Why did Batman design Robin's suit with only the underwear without pants?

one-liner vs script

A sentient carnivorous species trying to preserve life. How could they find a new food source?

Did Feynman cite a fallacy about only circles having the same width in all directions as a reason for the Challenger disaster?

Is the Olympic running race fair?

Should I withdraw my paper because the Editor is delaying the report?

How to make a gift without seeming creepy?

Why didn't Kes send Voyager home?

Wiring a pole barn that is 750' from my main power box

A Society Built Around Theft?

What is this cast-iron device on my water supply pipe?

How long should a test wait to assume that the result remains fixed

Could a small private island protect its sovereignty?

A fantasy saga with big bad trees that suddenly appear, and make demons appear

Can I use I2C over 2m cables?

Sanitise a high score table to remove offensive terms / usernames

Forced Conversion of Majority

Does the Creighton Method of Natural Family Planning have a failure rate of 3.2% or less?

How can I curtail abuse of the Illusion wizard's Illusory Reality feature?



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;









6

















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
    8 hours ago


















6

















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
    8 hours ago














6












6








6


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



share|improve this question








edited 7 hours ago









Ravindra Ranwala

14.5k5 gold badges28 silver badges45 bronze badges




14.5k5 gold badges28 silver badges45 bronze badges










asked 8 hours ago









AmitojAmitoj

1109 bronze badges




1109 bronze badges










  • 2





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

    – Federico Peralta Schaffner
    8 hours ago













  • 2





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

    – Federico Peralta Schaffner
    8 hours ago








2




2





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

– Federico Peralta Schaffner
8 hours ago






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

– Federico Peralta Schaffner
8 hours ago













4 Answers
4






active

oldest

votes


















5


















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
    7 hours ago







  • 2





    Yes, your comment was helpful. Good catch !

    – Ravindra Ranwala
    7 hours ago


















2


















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
      8 hours ago


















    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









      5


















      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
        7 hours ago







      • 2





        Yes, your comment was helpful. Good catch !

        – Ravindra Ranwala
        7 hours ago















      5


















      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
        7 hours ago







      • 2





        Yes, your comment was helpful. Good catch !

        – Ravindra Ranwala
        7 hours ago













      5














      5










      5









      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



      share|improve this answer








      edited 5 hours ago









      Naman

      52.8k14 gold badges114 silver badges217 bronze badges




      52.8k14 gold badges114 silver badges217 bronze badges










      answered 8 hours ago









      Ravindra RanwalaRavindra Ranwala

      14.5k5 gold badges28 silver badges45 bronze badges




      14.5k5 gold badges28 silver badges45 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
        7 hours ago







      • 2





        Yes, your comment was helpful. Good catch !

        – Ravindra Ranwala
        7 hours ago












      • 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
        7 hours ago







      • 2





        Yes, your comment was helpful. Good catch !

        – Ravindra Ranwala
        7 hours ago







      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
      7 hours ago






      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
      7 hours ago





      2




      2





      Yes, your comment was helpful. Good catch !

      – Ravindra Ranwala
      7 hours ago





      Yes, your comment was helpful. Good catch !

      – Ravindra Ranwala
      7 hours ago













      2


















      It would be straight forward,



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





      share|improve this answer






























        2


















        It would be straight forward,



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





        share|improve this answer




























          2














          2










          2









          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



          share|improve this answer










          answered 8 hours ago









          Code_ModeCode_Mode

          2,90812 silver badges22 bronze badges




          2,90812 silver badges22 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
                8 hours ago















              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
                8 hours ago













              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



              share|improve this answer








              edited 8 hours ago

























              answered 8 hours ago









              kgautronkgautron

              5,5967 gold badges33 silver badges57 bronze badges




              5,5967 gold badges33 silver badges57 bronze badges















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

                – Amitoj
                8 hours ago

















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

                – Amitoj
                8 hours ago
















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

              – Amitoj
              8 hours ago





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

              – Amitoj
              8 hours ago











              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



                  share|improve this answer










                  answered 7 hours ago









                  Federico Peralta SchaffnerFederico Peralta Schaffner

                  24.9k5 gold badges39 silver badges84 bronze badges




                  24.9k5 gold badges39 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

                      Canceling a color specificationRandomly assigning color to Graphics3D objects?Default color for Filling in Mathematica 9Coloring specific elements of sets with a prime modified order in an array plotHow to pick a color differing significantly from the colors already in a given color list?Detection of the text colorColor numbers based on their valueCan color schemes for use with ColorData include opacity specification?My dynamic color schemes

                      Invision Community Contents History See also References External links Navigation menuProprietaryinvisioncommunity.comIPS Community ForumsIPS Community Forumsthis blog entry"License Changes, IP.Board 3.4, and the Future""Interview -- Matt Mecham of Ibforums""CEO Invision Power Board, Matt Mecham Is a Liar, Thief!"IPB License Explanation 1.3, 1.3.1, 2.0, and 2.1ArchivedSecurity Fixes, Updates And Enhancements For IPB 1.3.1Archived"New Demo Accounts - Invision Power Services"the original"New Default Skin"the original"Invision Power Board 3.0.0 and Applications Released"the original"Archived copy"the original"Perpetual licenses being done away with""Release Notes - Invision Power Services""Introducing: IPS Community Suite 4!"Invision Community Release Notes

                      François Viète Contents Biography Work and thought Bibliography See also Notes Further reading External links Navigation menup. 21Google Bookspp. 75–77Google BooksDe thou (from University of Saint Andrews)ArchivedGoogle BooksGoogle BooksGoogle BooksGoogle booksGoogle Bookscc-parthenay.frL'histoire universelle (fr)Universal History (en)ArchivedAdsabs.harvard.eduPagesperso-orange.frArchive.orgChikara Sasaki. Descartes' mathematical thought p.259Google BooksGoogle BooksGoogle Bookspp. 152 and onwardGoogle BooksGoogle BooksScribd.comGoogle Books1257-7979Google BooksGoogle BooksGoogle BooksGoogle BooksGoogle BooksGoogle BooksGallica.bnf.frGoogle BooksGoogle Books"François Viète"Francois Viète: Father of Modern Algebraic NotationThe Lawyer and the GamblerAbout TarporleySite de Jean-Paul GuichardL'algèbre nouvelle"About the Harmonicon"cb120511976(data)1188044800000 0001 0913 5903n82164680ola2013766880073431702w6vt1sb70287374827140948071409480