Groovyで文字列を連結する最良の(慣用的な)方法は何ですか?
オプション1:
calculateAccountNumber(bank, branch, checkDigit, account) {
bank + branch + checkDigit + account
}
オプション2:
calculateAccountNumber(bank, branch, checkDigit, account) {
"$bank$branch$checkDigit$account"
}
古いGroovyのWebサイトで、このトピックに関する興味深い点を見つけました。できることはやり直します。
Javaと同様に、文字列を「+」記号で連結できます。ただし、Javaは、「+」式の2つの項目のうち、最初の場所であろうと最後の場所であろうと、どちらか一方が文字列である必要があるだけです。 Javaは、「+」式の非StringオブジェクトでtoString()メソッドを使用します。しかし、Groovyでは、「+」式の最初の項目が正しい方法でplus()メソッドを実装するだけで安全です。Groovyはそれを検索して使用するからです。 Groovy GDKでは、NumberおよびString/StringBuffer/Characterクラスのみに、文字列を連結するためのplus()メソッドが実装されています。驚きを避けるため、常にGStringsを使用してください。
私は常に2番目のメソッド(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 ) {
// 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
そのため、読みやすさとスピードを優先して、テンプレートを作成することをお勧めします;-)
注意:GStringメソッドの最後にtoString()
を追加して、出力タイプを他のメトリックと同じにし、より公平なテストにする場合、StringBuilder
およびStringBuffer
がGStringメソッドに勝って速度を上げます。ただし、ほとんどの場合、Stringの代わりにGStringを使用できるため(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よりも低速ですが、文字列を追加するよりも少し高速です...
しかし、まだずっと読みやすいです。
最新の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
def my_string = "some string"
println "here: " + my_string
上記の答えがベンチマーク、文字列バッファ、テストなどに行く必要がある理由はよくわかりません。
現在のハードウェアで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