javajava-8java-streamnested-propertiesnested-map

creating nested maps with nested properties from List, stream, Java 8


I made this question stream creating List of List (nested List) using forEach, Java 8

class EntityCompositeId {
    private Long firstId;
    private Long secondId;
    // getter & setter...
}

class EntityComposite {
    private EntityCompositeId id;
    private String first;
    private String second;
    // getter & setter...
}

List<EntityComposite> listEntityComposite = ....
Supose this content

1, 1, "firstA", "secondBirdOne"
1, 2, "firstA", "secondBirdTwo"
1, 3, "firstA", "secondBirdThree"

2, 1, "firstB", "secondCatOne"
2, 2, "firstB", "secondCatTwo"
2, 3, "firstB", "secondCatThree"

3, 1, "firstC", "secondDogOne"
3, 2, "firstC", "secondDogTwo"
3, 3, "firstC", "secondDogThree"

Map<Long, Map<Long, String>> listOfLists = new HashMap<>();

Now using stream I want to fill like:

 1 -> {1 ->"secondBirdOne", 2 -> "secondBirdTwo", 3 -> "secondBirdThree"}
 2 -> {1 ->"secondCatOne", 2 -> "secondCatTwo", 3 -> "secondCatThree"}
 3 -> {1 ->"secondDogOne", 2 -> "secondDogTwo", 3 -> "secondDogThree"}

My NOT functional code was:

    Map<Long, Map<Long, String>> listaMunDepa = listEntityComposite.stream()
        .collect(Collectors.groupingBy(
            e -> e.getId().getFirstId(),
            Collectors.toMap(f -> f.getId().getSecondId(), Function.identity()))
    );

second Try

    Map<Long, Map<Long, String>> listaMunDepa = listEntityComposite.stream()
        .collect(Collectors.groupingBy(
            e -> e.getId().getFirstId(),
            Collectors.groupingBy(EntityComposite::getId::getSecondId, EntityComposite::getSecond)) // How change this line
    );

Solution

  • You're really close, instead of passing Function.identity, you should pass EntityComposite::getSecond

    listEntityComposite.stream()
               .collect(groupingBy(e -> e.getId().getFirstId(),
                      toMap(f -> f.getId().getSecondId(), EntityComposite::getSecond)));
    

    because you supplied Function.identity the result was Map<Long, Map<Long, EntityComposite>>, so as shown above, you'll simply need to extract the getSecondId for the valueMapper function supplied to toMap hence yielding a Map<Long, Map<Long, String>>.