Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lambda & Stream : collect in a Map

I would like to build a Map using the Stream & Lambda couple.

I've tried many ways but I'm stucked. Here's the classic Java code to do it using both Stream/Lambda and classic loops.

Map<Entity, List<Funder>> initMap = new HashMap<>();
List<Entity> entities = pprsToBeApproved.stream()
    .map(fr -> fr.getBuyerIdentification().getBuyer().getEntity())
    .distinct()
    .collect(Collectors.toList());

for(Entity entity : entities) {
    List<Funder> funders = pprsToBeApproved.stream()
        .filter(fr -> fr.getBuyerIdentification().getBuyer().getEntity().equals(entity))
        .map(fr -> fr.getDocuments().get(0).getFunder())
        .distinct()
        .collect(Collectors.toList());
    initMap.put(entity, funders);
        }

As you can see, I only know how to collect in a list, but I just can't do the same with a map. That's why I have to stream my list again to build a second list to, finally, put all together in a map. I've also tried the 'collect.groupingBy' statement as it should too produce a map, but I failed.

like image 513
Lovegiver Avatar asked Oct 10 '18 13:10

Lovegiver


1 Answers

It seems you want to map whatever is on the pprsToBeApproved list to your Funder instances, grouping them by buyer Entity.

You can do it as follows:

Map<Entity, List<Funder>> initMap = pprsToBeApproved.stream()
    .collect(Collectors.groupingBy(
        fr -> fr.getBuyerIdentification().getBuyer().getEntity(), // group by this
        Collectors.mapping(
            fr -> fr.getDocuments().get(0).getFunder(), // mapping each element to this
            Collectors.toList())));                     // and putting them in a list

If you don't want duplicate funders for a particular entity, you can collect to a map of sets instead:

Map<Entity, Set<Funder>> initMap = pprsToBeApproved.stream()
    .collect(Collectors.groupingBy(
        fr -> fr.getBuyerIdentification().getBuyer().getEntity(),
        Collectors.mapping(
            fr -> fr.getDocuments().get(0).getFunder(),
            Collectors.toSet())));

This uses Collectors.groupingBy along with Collectors.mapping.

like image 104
fps Avatar answered Sep 23 '22 09:09

fps