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()))));