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;
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
add a comment
|
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
2
Do you have repeatedAelements in yourList<A>?
– Federico Peralta Schaffner
Oct 2 at 15:15
add a comment
|
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
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
java lambda java-8 java-stream collectors
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 repeatedAelements in yourList<A>?
– Federico Peralta Schaffner
Oct 2 at 15:15
add a comment
|
2
Do you have repeatedAelements in yourList<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
add a comment
|
4 Answers
4
active
oldest
votes
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())));
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
add a comment
|
It would be straight forward,
listofA.stream().collect(toMap(Function.identity(), a -> getListofB(a)));
add a comment
|
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)
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
add a comment
|
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)), anIllegalStateExceptionis thrown when the collection operation is performed. If the mapped keys may have duplicates, usetoMap(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).
add a comment
|
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
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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())));
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
add a comment
|
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())));
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
add a comment
|
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())));
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())));
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
add a comment
|
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
add a comment
|
It would be straight forward,
listofA.stream().collect(toMap(Function.identity(), a -> getListofB(a)));
add a comment
|
It would be straight forward,
listofA.stream().collect(toMap(Function.identity(), a -> getListofB(a)));
add a comment
|
It would be straight forward,
listofA.stream().collect(toMap(Function.identity(), a -> getListofB(a)));
It would be straight forward,
listofA.stream().collect(toMap(Function.identity(), a -> getListofB(a)));
answered Oct 2 at 14:59
Code_ModeCode_Mode
3,66215 silver badges25 bronze badges
3,66215 silver badges25 bronze badges
add a comment
|
add a comment
|
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)
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
add a comment
|
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)
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
add a comment
|
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)
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)
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
add a comment
|
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
add a comment
|
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)), anIllegalStateExceptionis thrown when the collection operation is performed. If the mapped keys may have duplicates, usetoMap(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).
add a comment
|
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)), anIllegalStateExceptionis thrown when the collection operation is performed. If the mapped keys may have duplicates, usetoMap(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).
add a comment
|
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)), anIllegalStateExceptionis thrown when the collection operation is performed. If the mapped keys may have duplicates, usetoMap(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).
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)), anIllegalStateExceptionis thrown when the collection operation is performed. If the mapped keys may have duplicates, usetoMap(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).
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
add a comment
|
add a comment
|
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.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
2
Do you have repeated
Aelements in yourList<A>?– Federico Peralta Schaffner
Oct 2 at 15:15