Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using java 8 streams api for nested lookup

How can we use java 8 streams api to get expected output here

A1 has B1, B2
A2 has B1, B2, B3

B1, B2 belong to C1
B3 belong to C2

So, for C1, count should be 4 as B1, B2 appears 4 times
Likewise count for C2 will be 1 as B3 appears 1 time

        List<String> A= new ArrayList<>();
        A.add("A1");
        A.add("A2");

        Map<String, List<String>> AMap = new HashMap<>();
        AMap.put("A1", Arrays.asList("B1", "B2"));
        AMap.put("A2", Arrays.asList("B1", "B2", "B3"));

        Map<String, String> BMap = new HashMap<>();
        CMap.put("B1", "C1");
        CMap.put("B2", "C1");
        CMap.put("B3", "C2");

Expected output

        C1 : 4 , C2 : 1
like image 322
fortm Avatar asked Jan 28 '23 17:01

fortm


2 Answers

For each key in the A list, I would fetch each B key which would fetch each C value from the CMap. Then flatmap the stream, group by identity and count the values.

import static java.util.Collections.emptyList;
import static java.util.function.Function.identity;
import static java.util.stream.Collectors.counting;
import static java.util.stream.Collectors.groupingBy;

...

Map<String, Long> res = A.stream()
         .flatMap(a -> AMap.getOrDefault(a, emptyList()).stream().map(BMap::get))
         .collect(groupingBy(identity(), counting()));
like image 190
Alexis C. Avatar answered Feb 08 '23 03:02

Alexis C.


In two steps...

List<String> all = AMap.values()
                       .stream()
                       .flatMap(Collection::stream)
                       .collect(Collectors.toList());


Map<String, Long> result = CMap.entrySet().stream()
            .collect(Collectors.groupingBy(
                    Entry::getValue,
                    Collectors.summingLong(
                            x -> all.stream().filter(y -> y.equals(x.getKey())).count())));

    System.out.println(result); // {C1=4, C2=1}
like image 33
Eugene Avatar answered Feb 08 '23 01:02

Eugene