我试图查询数据库并将结果存储在带有一些嵌套数据元素的Groovy地图数据结构中,但似乎无法弄明白。
这是我最近的尝试 -
#!/usr/bin/env groovy
import groovy.sql.Sql;
// code to connect to database omitted
TreeMap tsMap = [:];
def tabcount = 0, inxcount = 0;
dbconn.eachRow("SELECT table_name,tablespace_name FROM user_tables") {
tabcount += 1;
if (tsMap.containsKey(it.tablespace_name)) {
tsMap[it.tablespace_name].tabs++;
} else {
type = [tabs:1];
tsMap[it.tablespace_name] = type;
}
}
dbconn.eachRow("SELECT index_name,tablespace_name FROM user_indexes") {
inxcount += 1;
if (tsMap.containsKey(it.tablespace_name) {
tsMap[it.tablespace_name].inxs++;
} else {
type = [inxs:1];
tsMap[it.tablespace_name] = type;
}
}
tsMap.eachWithIndex { entry, i ->
printf("%3d - Tablespace: %-30s contains %4d tables and %4d indexes\n",
i, entry.key, entry.value.tabs, entry.value.inxs);
}
printf("Total table count = %d\n", tabcount);
printf("Total index count = %d\n", inxcount);
这就是我想让tsMap最终得到的结果 -
tsMap = [TS1:[tabs:10], TS2:[tabs:35, inxs:12]]
TS1条目(只有" table"条目,没有"索引"条目)有效,但只要有索引条目我最终会 -
tsMap = [TS1:[tabs:10], TS2:[inxs:12]]
尽管TS2除了12个索引外还有35个表。
我的目标是让tsMap看起来像 -
tsMap = [TS1:[tabs:10], TS2:[tabs:35, inxs:12]]
我在其他语言中使用关联数组,并在尝试在其中存储数组(任何类型)以创建复杂数据结构时遇到类似的挑战。有了Groovy的Java基础,我希望它简单明了,但如果是这样的话,我就会错过一些东西。
我已经对这段代码的复杂性感到不满,并希望能够指出如何简化它。我希望这是非常简单和直接的,甚至是微不足道的,我在某个地方转了一个错误,而且此时它只是简单的。
显然,我可以只有两张地图,最后会有 -
tabMap = [TS1:10, TS2:35]
inxMap = [TS2:12]
但当然这也是一种理解如何超越简单关联数组(地图)的练习,所以当我正在研究我的Groovy技能时,任何帮助都会受到赞赏。
基于@ cfrick的反馈,我已经尝试了这个,更简化的代码 -
TreeMap tsMap = [:].withDefault{ [tabs:0, inxs:0] };
def tabcount = 0, inxcount = 0;
workconn.eachRow("SELECT table_name,tablespace_name FROM user_tables") {
tsMap[it.tablespace_name].tabs++;
}
workconn.eachRow("SELECT index_name,tablespace_name FROM user_indexes") {
tsMap[it.tablespace_name].inxs++;
}
这看起来真的很有意义,我认为它会这样做但我最终会 -
Caught: java.lang.NullPointerException: Cannot get property 'tabs' on null object
java.lang.NullPointerException: Cannot get property 'tabs' on null object
之前我学到的是因为Groovy找不到带有"标签的嵌套地图"能够增加它的关键。
我认为.withDefault会将我的嵌套地图添加到任何"键"我添加到tsMap。
对于我出错的地方的任何建议表示赞赏。
好的,在@ cfrick的帮助下,目标正在运行,这是最终的代码:
#!/usr/bin/env groovy
import groovy.sql.Sql;
// code to connect to database omitted
// avoid types other than def as they cast away the .withDefault
def tsMap = [:].withDefault{ [tabs:0, inxs:0] };
workconn.eachRow("SELECT table_name,NVL(tablespace_name, '(null)') tsName FROM user_tables") {
tsMap[it.tsName].tabs++;
}
workconn.eachRow("SELECT index_name,NVL(tablespace_name, '(null)') tsName FROM user_indexes") {
tsMap[it.tsName].inxs++;
}
def fmt = (opt.geninput) ? "%d,%s,%d,%d,%s\n" : "%3d - Tablespace: %-25s contains %4d tables and %4d indexes %s\n";
tsMap = tsMap.sort(); // sort the keys
tsMap.eachWithIndex { entry, i ->
printf(fmt, i, entry.key, entry.value.tabs, entry.value.inxs, (entry.value.tabs * entry.value.inxs != 0) ? "**" : "");
}
printf("Total table count = %d\n", tsMap.values()*.tabs.sum());
printf("Total index count = %d\n", tsMap.values()*.inxs.sum());
谢谢!