groovy map在创建(略微)复杂数据结构时的使用困难

时间:2016-07-25 00:06:59

标签: groovy

我试图查询数据库并将结果存储在带有一些嵌套数据元素的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());

谢谢!

0 个答案:

没有答案