Search code examples
javacollectionshashmapjava-streamcollectors

How to Convert a List Into Map of Map Map<String, Map<String,Object>>


I have a List<Employee> e which I want to convert into Map<String, Map<String,Emp>> where the outer string should be "Name" and the inner string should be "Domain".

       Name Id Domain
e(0) - Emp1, 1, Insurance
e(1) - Emp1, 2, Sales
e(2) - Emp2, 3, Sales
e(3) - Emp4, 4, Marketing

I am tried the following-

e.stream().collect(Collectors.groupingBy(
                                   Employee::getName,
                                   toMap(Employee::getDomain,Emp)));

So the expected output map should look like

<Emp1>
     <Insurance, e(0)>
     <Sales, e(1)>
<Emp2>
     <Sales, e(2)>
<Emp4>
     <Marketing, e(3)>

But I get only unique values, actual output-

<Emp1>
     <Insurance, e(0)>
<Emp2>
     <Sales, e(2)>
<Emp4>
     <Marketing, e(3)>

Can someone tell the best way to do it?


Solution

  • What you are mostly looking for is nested grouping such as :

    Map<String, Map<String, List<Employee>>> groupedMap = employees.stream()
            .collect(Collectors.groupingBy(Employee::getName,
                    Collectors.groupingBy(Employee::getDomain, Collectors.toList())));
    

    Note - The values are List<Employee> which are the employees grouped by name and then by domain. (Both same clubbed into a List.)


    If you were to stricly adhere to getting a single employee corresponding to the specified grouping, the code pretty much works for me with a small modification:

    Map<String, Map<String, Employee>> groupedReducedMap = employees.stream()
            .collect(Collectors.groupingBy(Employee::getName,
                    Collectors.toMap(Employee::getDomain,
                            Function.identity(), // value as the employee instance
                            (a, b) -> a))); // choose first instance for similar 'domain'