Search code examples
javalistjava-8hashmapjava-stream

How to create Map of Map in Java from a List


I have a List of Root object List rootList;

class Root {
    int level;
    String path;
    String siteId;
    String siteName;
}

In this object, level & path are not unique. For example Level can be 2 and path can be 1.2.3, 1.3.4, 1.5.6... etc and the site can be multiple for a single path. I want to convert rootList to Map<level, Map<Path, List<Root>> sites;Now for each level and path, I can bring the List of Sites.

If I use, Stream Foreach, I am not able to get the List and this approach is not at all working. Please kindly help me in bringing this structure.

rootList.stream().forEach(root -> sites.put(root.getLevel(), root.getPath())).;

Solution

  • You can use Collectors to do this:

    First a groupingBy collector to create the top level map, which uses another groupingBy collector to create each sub map, with the values populated by a toList.

    package com.example.so;
    
    import java.util.List;
    import java.util.Map;
    import java.util.stream.Collectors;
    
    
    public class Eg {
    
    
        public static void main(String[] args) {
            List<Root> roots = List.of(
                    new Root(1, "A", "B"),
                    new Root(1, "A", "C"),
                    new Root(2, "A", "B"),
                    new Root(2, "A", "C"),
                    new Root(1, "Z", "B"),
                    new Root(1, "Z", "C"),
                    new Root(2, "Z", "B"),
                    new Root(2, "Z", "C")
            );
            Map<Integer, Map<String,List<Root>>> maps = roots.stream().collect(Collectors.groupingBy(
                    Root::level,
                    Collectors.groupingBy(Root::path, Collectors.toList())
            ));
            System.out.println(maps);
        }
    
    }
    
    record Root(int level, String path, String siteId) {
    }
    

    Which produces the structure:

     {
     1=
       {
       A=[Root[level=1, path=A, siteId=B], Root[level=1, path=A, siteId=C]],
       Z=[Root[level=1, path=Z, siteId=B], Root[level=1, path=Z, siteId=C]]
       },
     2=
       {
       A=[Root[level=2, path=A, siteId=B], Root[level=2, path=A, siteId=C]],
       Z=[Root[level=2, path=Z, siteId=B], Root[level=2, path=Z, siteId=C]]
       }
     }