4

Given we have a list of Bank, each Bank have multiple offices,

public class Bank {
   private String name;
   private List<String> branches;
   public String getName(){
       return name;
   }
   public List<String> getBranches(){
       return branches;
   }
}

For example:

Bank "Mizuho": branches=["London", "New York"]
Bank "Goldman": branches = ["London", "Toronto"]

Given a list of banks, I would have a map of bank representation for each city. In the example above, I need a result of

Map["London"] == ["Mizuho", "Goldman"]
Map["New York"] == ["Mizuho"]
Map["Toronto"] == ["Goldman"]

How can I achieve that result using Java 8 API? Using pre-Java8 is easy, but verbose. Thank you.

4 Answers 4

6
Map<String, Set<Bank>> result = new HashMap<>();
for (Bank bank : banks) {
    for (String branch : bank.getBranches()) {
        result.computeIfAbsent(branch, b -> new HashSet<Bank>()).add(bank);
    }
}
Sign up to request clarification or add additional context in comments.

Comments

4
 banks.flatMap(bank -> bank.getBranches()
             .stream()
             .map(branch -> new AbstractMap.SimpleEntry<>(branch, bank)))
       .collect(Collectors.groupingBy(
             Entry::getKey, 
             Collectors.mapping(Entry::getValue, Collectors.toList())));

Result would be:

{London=[Mizuho, Goldman], NewYork=[Mizuho], Toronto=[Goldman]}

Comments

1

You could do it using the version of Stream.collect that accepts a supplier, an accumulator function and a combiner function, as follows:

Map<String, List<Bank>> result = banks.stream()
    .collect(
        HashMap::new,
        (map, bank) -> bank.getBranches().forEach(branch ->
            map.computeIfAbsent(branch, k -> new ArrayList<>()).add(bank)),
        (map1, map2) -> map2.forEach((k, v) -> map1.merge(k, v, (l1, l2) -> {
            l1.addAll(l2);
            return l1;
        })));

Comments

0

I think solution provided by @JB Nizet is one of the most simple/efficient solutions. it can also be rewritten by forEach

banks.forEach(b -> b.getBranches().forEach(ch -> result.computeIfAbsent(ch, k -> new ArrayList<>()).add(b)));

Another short solution by Stream with abacus-common

Map<String, List<Bank>> res = Stream.of(banks)
          .flatMap(e -> Stream.of(e.getBranches()).map(b -> Pair.of(b, e)))
          .collect(Collectors.toMap2());
    

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.