使用Groovy字符串连接(String concatenation with Groovy)

2019-06-26 01:58发布

什么是最好的(习惯)的方式来连接字符串在Groovy?

选项1:

calculateAccountNumber(bank, branch, checkDigit, account) {
    bank + branch + checkDigit + account
}

选项2:

calculateAccountNumber(bank, branch, checkDigit, account) {
    "$bank$branch$checkDigit$account"
}

我创办了一个有趣的关于此主题的旧Groovy的网站:事情可以做,但最好离开百废待兴。

正如在Java中,你可以用“+”符号连接字符串。 但Java只需要一个“+”表达的两个项目之一,是一个字符串,不管它是在第一时间,或在最后一个。 Java将在您的“+”表达的非String对象使用toString()方法。 但在Groovy中,你只应该是安全的“+”表达的第一个项目实现以正确的方式加号()方法,因为Groovy会搜索并使用它。 在Groovy GDK,只有数字和字符串/ StringBuffer的/字符类必须实现的连接字符串的加号()方法。 为了避免意外,请始终使用GString的。

Answer 1:

我经常去的第二个方法(使用GString型模板),但是当有超过一对夫妇的参数更像你的,我倾向于将它们包装在${X}因为我觉得它比较易读。

运行一些基准(用永井正人的优良GBench模块上这些方法)还示出模板比其它方法更快:

@Grab( 'com.googlecode.gbench:gbench:0.3.0-groovy-2.0' )
import gbench.*

def (foo,bar,baz) = [ 'foo', 'bar', 'baz' ]
new BenchmarkBuilder().run( measureCpuTime:false ) {
  // Just add the strings
  'String adder' {
    foo + bar + baz
  }
  // Templating
  'GString template' {
    "$foo$bar$baz"
  }
  // I find this more readable
  'Readable GString template' {
    "${foo}${bar}${baz}"
  }
  // StringBuilder
  'StringBuilder' {
    new StringBuilder().append( foo )
                       .append( bar )
                       .append( baz )
                       .toString()
  }
  'StringBuffer' {
    new StringBuffer().append( foo )
                      .append( bar )
                      .append( baz )
                      .toString()
  }
}.prettyPrint()

这给了我在我的机器上输出如下:

Environment
===========
* Groovy: 2.0.0
* JVM: Java HotSpot(TM) 64-Bit Server VM (20.6-b01-415, Apple Inc.)
    * JRE: 1.6.0_31
    * Total Memory: 81.0625 MB
    * Maximum Memory: 123.9375 MB
* OS: Mac OS X (10.6.8, x86_64) 

Options
=======
* Warm Up: Auto 
* CPU Time Measurement: Off

String adder               539
GString template           245
Readable GString template  244
StringBuilder              318
StringBuffer               370

因此,与可读性和速度在它的青睐,我建议模板;-)

注:如果您添加toString()到GString型方法最终使输出类型一样的其他指标,使之更公平的测试, StringBuilderStringBuffer跳动速度GString型方法。 然而,随着的GString来代替字符串的大部分东西被使用(你只需要锻炼与地图键和SQL语句慎用),它可以被大多没有留下这最后的转换

添加这些测试(因为它已被要求在评论)

  'GString template toString' {
    "$foo$bar$baz".toString()
  }
  'Readable GString template toString' {
    "${foo}${bar}${baz}".toString()
  }

现在我们得到的结果:

String adder                        514
GString template                    267
Readable GString template           269
GString template toString           478
Readable GString template toString  480
StringBuilder                       321
StringBuffer                        369

因此,大家可以看到(我说),它比的StringBuilder或StringBuffer的更慢,但还是有点不是添加字符串快...

但是,仍然有许多更具可读性。

通过下面ruralcoder评论后编辑

更新到最新的gbench,进行连结,并初始化为一个良好的大小StringBuilder的测试更大的字符串:

@Grab( 'org.gperfutils:gbench:0.4.2-groovy-2.1' )

def (foo,bar,baz) = [ 'foo' * 50, 'bar' * 50, 'baz' * 50 ]
benchmark {
  // Just add the strings
  'String adder' {
    foo + bar + baz
  }
  // Templating
  'GString template' {
    "$foo$bar$baz"
  }
  // I find this more readable
  'Readable GString template' {
    "${foo}${bar}${baz}"
  }
  'GString template toString' {
    "$foo$bar$baz".toString()
  }
  'Readable GString template toString' {
    "${foo}${bar}${baz}".toString()
  }
  // StringBuilder
  'StringBuilder' {
    new StringBuilder().append( foo )
                       .append( bar )
                       .append( baz )
                       .toString()
  }
  'StringBuffer' {
    new StringBuffer().append( foo )
                      .append( bar )
                      .append( baz )
                      .toString()
  }
  'StringBuffer with Allocation' {
    new StringBuffer( 512 ).append( foo )
                      .append( bar )
                      .append( baz )
                      .toString()
  }
}.prettyPrint()

Environment
===========
* Groovy: 2.1.6
* JVM: Java HotSpot(TM) 64-Bit Server VM (23.21-b01, Oracle Corporation)
    * JRE: 1.7.0_21
    * Total Memory: 467.375 MB
    * Maximum Memory: 1077.375 MB
* OS: Mac OS X (10.8.4, x86_64)

Options
=======
* Warm Up: Auto (- 60 sec)
* CPU Time Measurement: On

                                    user  system  cpu  real

String adder                         630       0  630   647
GString template                      29       0   29    31
Readable GString template             32       0   32    33
GString template toString            429       0  429   443
Readable GString template toString   428       1  429   441
StringBuilder                        383       1  384   396
StringBuffer                         395       1  396   409
StringBuffer with Allocation         277       0  277   286


Answer 2:

def my_string = "some string"
println "here: " + my_string 

不明白为什么上述需要的答案进入基准,串缓冲区,试验等。



Answer 3:

再生tim_yates对当前硬件回答并添加leftShift()和concat()方法来检查发现:

  'String leftShift' {
    foo << bar << baz
  }
  'String concat' {
    foo.concat(bar)
       .concat(baz)
       .toString()
  }

结果显示CONCAT()是一个纯字符串更快的解决方案,但如果你能处理的GString别的地方,GString的模板仍然领先,而荣誉奖应该去leftShift()(位运算符)和StringBuffer()的初始分配:

Environment
===========
* Groovy: 2.4.8
* JVM: OpenJDK 64-Bit Server VM (25.191-b12, Oracle Corporation)
    * JRE: 1.8.0_191
    * Total Memory: 238 MB
    * Maximum Memory: 3504 MB
* OS: Linux (4.19.13-300.fc29.x86_64, amd64)

Options
=======
* Warm Up: Auto (- 60 sec)
* CPU Time Measurement: On

                                    user  system  cpu  real

String adder                         453       7  460   469
String leftShift                     287       2  289   295
String concat                        169       1  170   173
GString template                      24       0   24    24
Readable GString template             32       0   32    32
GString template toString            400       0  400   406
Readable GString template toString   412       0  412   419
StringBuilder                        325       3  328   334
StringBuffer                         390       1  391   398
StringBuffer with Allocation         259       1  260   265


文章来源: String concatenation with Groovy