鉴于我们有一个银行清单,每个银行都有多个办事处,
public class Bank {
private String name;
private List<String> branches;
public String getName(){
return name;
}
public List<String> getBranches(){
return branches;
}
}
例如:
Bank "Mizuho": branches=["London", "New York"]
Bank "Goldman": branches = ["London", "Toronto"]
根据银行名单,我会得到每个城市的银行代表地图。在上面的例子中,我需要
的结果Map["London"] == ["Mizuho", "Goldman"]
Map["New York"] == ["Mizuho"]
Map["Toronto"] == ["Goldman"]
如何使用Java 8 API实现该结果?使用pre-Java8很容易,但很冗长。 谢谢。
答案 0 :(得分: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);
}
}
答案 1 :(得分: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())));
结果将是:
{London=[Mizuho, Goldman], NewYork=[Mizuho], Toronto=[Goldman]}
答案 2 :(得分:1)
您可以使用接受供应商,累加器功能和组合器功能的Stream.collect
版本来执行此操作,如下所示:
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;
})));
答案 3 :(得分:0)
我认为@JB Nizet提供的解决方案是最简单/最有效的解决方案之一。它也可以由forEach重写
banks.forEach(b -> b.getBranches().forEach(ch -> result.computeIfAbsent(ch, k -> new ArrayList<>()).add(b)));
Stream与AbacusUtil
的另一个简短解决方案Map<String, List<Bank>> res = Stream.of(banks)
.flatMap(e -> Stream.of(e.getBranches()).map(b -> Pair.of(b, e)))
.collect(Collectors.toMap2());