Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Group objects by multiple attributes with Java 8 stream API

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.

like image 723
haint504 Avatar asked Dec 18 '22 07:12

haint504


2 Answers

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);
    }
}
like image 88
JB Nizet Avatar answered Feb 16 '23 01:02

JB Nizet


 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]}
like image 42
Eugene Avatar answered Feb 16 '23 00:02

Eugene