Groovy收集字符串列表

时间:2015-08-14 12:40:47

标签: collections groovy

我试图创建一个粗略的json输出器,它接收一个键值对列表并产生相应的json。这就是我所拥有的:

class keyValuePairs {
    private String[][] contents
    keyValuePairs(String[][] inputList) {
        contents = inputList
    }

    public String json() {
        String jsonString = '{\n'
        String[] keyVals = contents collect {jsonPair it}
        jsonString += keyVals.join(',\n') + '\n'
        jsonString += '}'
        return jsonString
    }

    String jsonPair(String[] keyVal) {
        return '  "' + keyVal[0] + '": "' + keyVal[1] + '"'
    }
}

我的keyValuesPairs接受一个字符串列表列表,这个编译很好,但我的内容收集{jsonPair it} 行失败了:

Caught: groovy.lang.MissingMethodException: No signature of method: auditconfigprototype.keyValuePairs.jsonPair() is applicable for argument types: (auditconfig
prototype.keyValuePairs) values: [auditconfigprototype.keyValuePairs@7fa98a66]
Possible solutions: jsonPair([Ljava.lang.String;), json()

我可以回到内容上的循环,但我想采用收集的功能方法。但是,似乎每次尝试(甚至是微不足道的!)都会在我的内容列表上执行收集失败。我将列表定义错了吗?我应该如何在字符串列表列表中使用收集

1 个答案:

答案 0 :(得分:2)

你得到的例外是由于这一行:

String[] keyVals = contents collect {jsonPair it}

乍一看,这似乎相当于:

String[] keyVals = contents.collect {jsonPair it}

但事实上,你得到的是:

String[] keyVals = contents(collect() {jsonPair it})

解释

分配 keyVals 变量时, keyValuePairs 实例上正在调用 collect()方法;在这个上。

collect()然后遍历包含单个项目的List,即 keyValuePairs 的实例,并使用 keyValuePairs 实例调用闭包。 jsonPair()方法需要 String 数组,但会收到 keyValuePairs 。这就是抛出异常的原因:

groovy.lang.MissingMethodException: No signature of method: keyValuePairs.jsonPair() is applicable for argument types: (keyValuePairs) values: [keyValuePairs@63169fe0]

解决方案

解决方案是简单地添加缺失的句点以使代码如下:

String[] keyVals = contents.collect {jsonPair it}

Groovy-ier解决方案

作为练习,这是实现解析器的另一种方法。

def a = [
    ['firstname', 'John'],
    ['lastname', 'Doe'],
    ['language', 'Groovy']
]

class KeyValuePairs {
    def pairs

    String json() {
        new StringBuilder('{\n').with {
            append(
                pairs
                    .collect { String.format('"%s":"%s"', it[0], it[1]) }
                    .collect { "\t$it" }.join(',\n'))

            append '\n}\n'
        }.toString()
    }
}

def parser = new KeyValuePairs(pairs: a)
parser.json()
  • 此实现使用列表< 列表>而不是数组,因为Groovy对它们有很好的内置支持。

  • 通过使用Groovy Beans,可以创建 KeyValuePairs 实例,而无需显式创建样板构造函数。

  • 使用 StringBuilder 代替字符串连接。主要是因为我认为它使代码看起来更好。

  • 由于格式化需要双引号,我使用 String.format()。这使格式化易于阅读。注意:通常我会使用GString

  • 由于格式化的应用非常简洁,我取消了 jsonPair()方法。

第一个 collect()会产生如下输出:

[
    '"firstname":"John"', 
    '"lastname":"Doe"', 
    '"language":"Groovy"'
]

第二个 collect()在每对的双引号前添加一个TAB。最后, join()构建单个String对。

其他改进

另一种改进代码的方法是替换

it[0], it[1]

it.key, it.value

这可以通过用这两个替换第一个 collect()来完成:

.collect { [['key', 'value'], it].transpose().collectEntries() }
.collect { String.format('"%s":"%s"', it.key, it.value) }

我希望这会有所帮助:)

推荐阅读