我通常采用第二种方法(使用GString模板),但当像您这样有多个参数时,我倾向于将它们用${X}
包装起来,因为我发现这样更易读。
在这些方法上运行一些基准测试(使用Nagai Masato的出色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 ) {
'String adder' {
foo + bar + baz
}
'GString template' {
"$foo$bar$baz"
}
'Readable GString template' {
"${foo}${bar}${baz}"
}
'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
所以从易读性和速度方面考虑,我建议使用模板;-)
请注意:如果您在GString方法的末尾添加toString(),使输出类型与其他指标相同,并进行公平测试,则StringBuilder和StringBuffer在速度上胜过GString方法。但是,由于GString可以替代大多数String(只需小心处理Map键和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 {
'String adder' {
foo + bar + baz
}
'GString template' {
"$foo$bar$baz"
}
'Readable GString template' {
"${foo}${bar}${baz}"
}
'GString template toString' {
"$foo$bar$baz".toString()
}
'Readable GString template toString' {
"${foo}${bar}${baz}".toString()
}
'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
.toString()
并重新运行测试。我的运行结果显示它们的性能几乎与String adder
相同。我猜想你运行的测试实际上没有处理连接操作,只是创建了一个GString对象并存储了引用。如果你需要在某个时刻得到一个String
,那么StringBuilder
仍然是最快的选择。 - OverZealous