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;
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
8 hours ago
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 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 repeatedAelements in yourList<A>?
– Federico Peralta Schaffner
8 hours ago
add a comment
|
2
Do you have repeatedAelements in yourList<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
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
7 hours ago
2
Yes, your comment was helpful. Good catch !
– Ravindra Ranwala
7 hours ago
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
8 hours ago
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
7 hours ago
2
Yes, your comment was helpful. Good catch !
– Ravindra Ranwala
7 hours ago
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
7 hours ago
2
Yes, your comment was helpful. Good catch !
– Ravindra Ranwala
7 hours ago
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 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
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
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
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 8 hours ago
Code_ModeCode_Mode
2,90812 silver badges22 bronze badges
2,90812 silver badges22 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
8 hours ago
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
8 hours ago
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 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
add a comment
|
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
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 7 hours ago
Federico Peralta SchaffnerFederico Peralta Schaffner
24.9k5 gold badges39 silver badges84 bronze badges
24.9k5 gold badges39 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
8 hours ago