[英]How to create nested maps from flat sql select result set
具有类似于以下内容的 SQL 查询:
SELECT DISTINCT REGION, COUNTRY, CITY
产生这个结果集
REGION COUNTRY CITY EUROPE FRANCE PARIS EUROPE FRANCE LYON EUROPE FRANCE NICE EUROPE GERMANY BERLIN EUROPE GERMANY DORTMUND EUROPE GERMANY HANNOVER
有没有办法使用谷歌的 ListMultimap 以便我最终得到一个键 -> 值 -> 值结构?
例如
{EUROPE
{GERMANY
{BERLIN, DORTMUND, HANNOVER},
FRANCE
{PARIS, LYON, NICE}
}
}
或者另一个包更适合这个?
编辑:
尝试实施@Prog_G 的解决方案,但使用以下方法内存不足。 我认为最后我必须将外部转换为另一种数据结构。 我会以某种方式从中创建地图吗? 附注。 真实的例子更深一层,但为了这个问题,想让它更简单。
private static class GeoRowMapper implements RowCallbackHandler {
ListMultimap<String, ListMultimap<String, ListMultimap<String, String>>> outer = ArrayListMultimap.create();
ListMultimap<String, ListMultimap<String, String>> middle = ArrayListMultimap.create();
ListMultimap<String, String> inner = ArrayListMultimap.create();
@Override
public void processRow(ResultSet rs) throws SQLException {
String region = rs.getString("region");
String country = rs.getString("country");
String city = rs.getString("city");
String address = rs.getString("address");
inner.put(city, address);
middle.put(country, inner);
outer.put(region, middle);
}
public ListMultimap<String, ListMultimap<String, ListMultimap<String, List<String>>>> get() {
return Multimaps.asMap(outer);
}
}
根据安迪特纳的评论,您可以使用Table
。 在你的情况下,它会是这样的:
ImmutableTable<Region, Country, ImmutableList<City>> immutableTable = RECORDS.stream()
.collect(toImmutableTable(
r -> r.getRegion(),
r -> r.getCountry(),
r -> ImmutableList.of(r.getCity()),
(l, l2) -> ImmutableList.<City>builder().addAll(l).addAll(l2).build()
));
或者,如果您想要可变表作为结果:
Table<Region, Country, List<City>> table = RECORDS.stream()
.collect(toTable(
r -> r.getRegion(),
r -> r.getCountry(),
r -> Lists.newArrayList(r.getCity()),
(l, l2) -> {
l.addAll(l2);
return l;
},
HashBasedTable::create
));
与作品stream()
和Collectors.groupingBy
(学分去这里,又见此)。 Set
而不是List
保证了唯一的元素。
Map<String, Map<String, Set<String>>> grouped =
records.stream()
.collect(Collectors.groupingBy(r -> r.region,
Collectors.groupingBy(r -> r.country,
Collectors.mapping(r -> r.city, Collectors.toSet()))));
给予
class Record {
String city;
String region;
String country;
}
目前,这实际上会给你HashMap
和一个HashSet
。 他们的问题是在迭代他们的条目时缺乏保证的顺序。 如果结构应该支持用户界面中显示的树,则您也没有可用的重新排序或“在索引处插入”操作。 例如LinkedHashMap和TreeSet具有可预测的迭代顺序。 在创建最终的树数据结构时,这种方法仍然可以作为中间步骤。
根据您的口味, Map.computeIfAbsent
的使用可能是一个选项,它是在引入multimaps时引入的。
public Map<String, Map<String, Set<String>>> mumap(List<Record> records) {
Map<String, Map<String, Set<String>>> result = new LinkedHashMap<>();
for (Record r : records) {
result.computeIfAbsent(r.region, region -> new LinkedHashMap<>())
.computeIfAbsent(r.country, country -> new TreeSet<>())
.add(r.city);
}
return result;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.