Zawsze wybieram drugą metodę (używając szablonu GString), chociaż gdy jest więcej niż kilka parametrów, takich jak ty, staram się je zawijać, ${X}
ponieważ uważam, że jest to bardziej czytelne.
Uruchomienie niektórych testów porównawczych (przy użyciu doskonałego modułu GBench Nagai Masato ) na tych metodach również pokazuje, że tworzenie szablonów jest szybsze niż w przypadku innych metod:
@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()
To daje mi następujący wynik na moim komputerze:
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
Więc mając na względzie czytelność i szybkość, polecam tworzenie szablonów ;-)
Uwaga: jeśli dodasz toString()
na końcu metody GString, aby typ wyniku był taki sam jak inne metryki i uczynił go bardziej sprawiedliwym testem, StringBuilder
i StringBuffer
pokonał metody GString pod względem szybkości. Jednakże, ponieważ GString może być używany zamiast String dla większości rzeczy (wystarczy zachować ostrożność przy użyciu kluczy Map i instrukcji SQL), można go przeważnie pozostawić bez tej ostatecznej konwersji
Dodanie tych testów (o co pytano w komentarzach)
'GString template toString' {
"$foo$bar$baz".toString()
}
'Readable GString template toString' {
"${foo}${bar}${baz}".toString()
}
Teraz otrzymujemy wyniki:
String adder 514
GString template 267
Readable GString template 269
GString template toString 478
Readable GString template toString 480
StringBuilder 321
StringBuffer 369
Jak widać (jak powiedziałem), jest wolniejszy niż StringBuilder lub StringBuffer, ale wciąż nieco szybszy niż dodawanie ciągów znaków ...
Ale wciąż dużo bardziej czytelny.
Edytuj po komentarzu wiejscodera poniżej
Zaktualizowano do najnowszego gbencha, większych ciągów do konkatenacji i testu z inicjalizacją StringBuilder do dobrego rozmiaru:
@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()
daje
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()
dołączeniem do dwóch testów GString. Mój bieg pokazuje, że wtedy działają prawie tak samo jakString adder
. Domyślam się, że test, który przeprowadziłeś, tak naprawdę nie obsługuje konkatenacji, więc po prostu tworzy obiekt GString i przechowuje referencje.StringBuilder
jest nadal najszybszy, bez dwóch zdań, jeśli będziesz potrzebowaćString
w którymś momencie.