Java – use groupingby for nested maps, but collect different types of objects
So I have the code for this "work" (replace some names for simplicity):
Map<String,Map<String,ImmutableList<SomeClassA>>> someMap =
someListOfClassA.stream()
.filter(...)
.collect(Collectors.groupingBy(SomeClassA::someCriteriaA,Collectors.groupingBy(SomeClassA::someCriteriaB,GuavaCollectors.toImmutableList()
)
));
However, I want to change this code so that after grouping through the someclassa field, the internal collection is someclassb For example, if the class looks like this:
Suppose they all have all args constructors
class SomeClassA {
String someCriteriaA;
String someCriteriaB;
T someData;
String someId;
}
class SomeClassB {
T someData;
String someId;
}
And there is one way:
public static Collection<SomeClassB> getSomeClassBsFromSomeClassA(SomeClassA someA) {
List<Some List of Class B> listOfB = someMethod(someA);
return listOfB; // calls something using someClassA,gets a list of SomeClassB
}
I want to flatten the result list of someclass BS to
Map<String,ImmutableList<SomeClassB>>> someMap =
someListOfClassA.stream()
.filter(...)
. // not sure how to group by SomeClassA fields but result in a list of SomeClassB since one SomeClassA can result in multiple SomeClassB
I'm not sure how this will fit the code above How to collect a bunch of lists based on someclassb into a single list of all values of someclassa? If a single classA maps to a single ClassB, I know how to use collectors Mapping makes it work, but since each classA leads to multiple classbs, I don't know how to make it work
Any ideas would be appreciated thank you!
Solution
Use a custom collector like this:
private static Collector<Collection<SomeClassB>,?,ImmutableList<SomeClassB>>
flatMapToImmutableList() {
return Collectors.collectingAndThen(Collectors.toList(),listOfCollectionsOfB ->
listOfCollectionsOfB.stream()
.flatMap(Collection::stream)
.collect(GuavaCollectors.toImmutableList()));
}
You can achieve your goals:
Map<String,List<SomeClassB>>> someMap =
someListOfClassA.stream()
.filter(...)
.collect(Collectors.groupingBy(SomeClassA::getSomeCriteriaA,Collectors.groupingBy(SomeClassA::getSomeCriteriaB,Collectors.mapping(a -> getSomeClassBsFromSomeClassA(a),flatMapToImmutableList()))));
