string 使用 Groovy 进行字符串连接
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11359333/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
String concatenation with Groovy
提问by Arturo Herrero
What is the best (idiomatic) way to concatenate Strings in Groovy?
在 Groovy 中连接字符串的最佳(惯用)方法是什么?
Option 1:
选项1:
calculateAccountNumber(bank, branch, checkDigit, account) {
bank + branch + checkDigit + account
}
Option 2:
选项 2:
calculateAccountNumber(bank, branch, checkDigit, account) {
"$bank$branch$checkDigit$account"
}
I've founded an interesting point about this topic in the old Groovy website: Things you can do but better leave undone.
我在旧的 Groovy 网站上建立了一个关于这个主题的有趣观点:你可以做但最好不要做的事情。
As in Java, you can concatenate Strings with the "+" symbol. But Java only needs that one of the two items of a "+" expression to be a String, no matter if it's in the first place or in the last one. Java will use the toString() method in the non-String object of your "+" expression. But in Groovy, you just should be safe the first item of your "+" expression implements the plus() method in the right way, because Groovy will search and use it. In Groovy GDK, only the Number and String/StringBuffer/Character classes have the plus() method implemented to concatenate strings. To avoid surprises, always use GStrings.
与在 Java 中一样,您可以将字符串与“+”符号连接起来。但是Java只需要“+”表达式的两项中的一项是字符串,无论它是在第一位还是在最后一位。Java 将在“+”表达式的非 String 对象中使用 toString() 方法。但是在 Groovy 中,您应该确保“+”表达式的第一项以正确的方式实现 plus() 方法,因为 Groovy 会搜索并使用它。在 Groovy GDK 中,只有 Number 和 String/StringBuffer/Character 类实现了 plus() 方法来连接字符串。为避免意外,请始终使用 GStrings。
回答by tim_yates
I always go for the second method (using the GString template), though when there are more than a couple of parameters like you have, I tend to wrap them in ${X}
as I find it makes it more readable.
我总是采用第二种方法(使用 GString 模板),但是当像您这样有多个参数时,我倾向于将它们包装起来,${X}
因为我发现它更具可读性。
Running some benchmarks (using Nagai Masato's excellent GBench module) on these methods also shows templating is faster than the other methods:
在这些方法上运行一些基准测试(使用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 ) {
// 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()
That gives me the following output on my machine:
这给了我机器上的以下输出:
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
So with readability and speed in it's favour, I'd recommend templating ;-)
因此,以可读性和速度为优势,我建议使用模板 ;-)
NB: If you add toString()
to the end of the GString methods to make the output type the same as the other metrics, and make it a fairer test, StringBuilder
and StringBuffer
beat the GString methods for speed. However as GString can be used in place of String for most things (you just need to exercise caution with Map keys and SQL statements), it can mostly be left without this final conversion
注意:如果您添加toString()
到 GString 方法的末尾以使输出类型与其他指标相同,并使其成为更公平的测试,StringBuilder
并StringBuffer
在速度方面击败 GString 方法。然而,由于 GString 可以在大多数情况下代替 String 使用(您只需要小心使用 Map 键和 SQL 语句),因此大多数情况下它可以不进行最终转换
Adding these tests (as it has been asked in the comments)
添加这些测试(正如评论中所要求的那样)
'GString template toString' {
"$foo$bar$baz".toString()
}
'Readable GString template toString' {
"${foo}${bar}${baz}".toString()
}
Now we get the results:
现在我们得到结果:
String adder 514
GString template 267
Readable GString template 269
GString template toString 478
Readable GString template toString 480
StringBuilder 321
StringBuffer 369
So as you can see (as I said), it is slower than StringBuilder or StringBuffer, but still a bit faster than adding Strings...
所以正如你所看到的(正如我所说),它比 StringBuilder 或 StringBuffer 慢,但仍然比添加字符串快一点......
But still lots more readable.
但仍然更具可读性。
Edit after comment by ruralcoder below
在下面的乡村编码器评论后编辑
Updated to latest gbench, larger strings for concatenation and a test with a StringBuilder initialised to a good size:
更新到最新的 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()
gives
给
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
回答by Snowcrash
def my_string = "some string"
println "here: " + my_string
Not quite sure why the answer above needs to go into benchmarks, string buffers, tests, etc.
不太确定为什么上面的答案需要进入基准测试、字符串缓冲区、测试等。
回答by thoroc
Reproducing tim_yates answer on current hardware and adding leftShift() and concat() method to check the finding:
在当前硬件上重现 tim_yates 答案并添加 leftShift() 和 concat() 方法来检查发现:
'String leftShift' {
foo << bar << baz
}
'String concat' {
foo.concat(bar)
.concat(baz)
.toString()
}
The outcome shows concat() to be the faster solution for a pure String, but if you can handle GString somewhere else, GString template is still ahead, while honorable mention should go to leftShift() (bitwise operator) and StringBuffer() with initial allocation:
结果表明 concat() 是纯 String 的更快解决方案,但如果您可以在其他地方处理 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