Reputation: 103
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.
Upvotes: 4
Views: 1803
Reputation: 1244
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());
Upvotes: 0
Reputation: 34450
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;
})));
Upvotes: 1
Reputation: 120848
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]}
Upvotes: 4
Reputation: 691635
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);
}
}
Upvotes: 6