Eu sempre escolho o segundo método (usando o modelo GString), embora quando há mais do que alguns parâmetros como você, eu tendo a envolvê-los, ${X}
pois acho que os torna mais legíveis.
Executar alguns benchmarks (usando o excelente módulo GBench de Nagai Masato ) nesses métodos também mostra que a modelagem é mais rápida do que os outros métodos:
@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()
Isso me dá a seguinte saída em minha máquina:
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
Portanto, com legibilidade e velocidade a seu favor, eu recomendo criar modelos ;-)
NB: Se você adicionar toString()
ao final dos métodos GString para tornar o tipo de saída o mesmo que as outras métricas, torná-lo um teste mais justo StringBuilder
e StringBuffer
vencer os métodos GString para velocidade. No entanto, como GString pode ser usado no lugar de String para a maioria das coisas (você só precisa ter cuidado com as chaves de mapa e instruções SQL), ele pode ser deixado na maioria das vezes sem esta conversão final
Adicionando esses testes (como foi perguntado nos comentários)
'GString template toString' {
"$foo$bar$baz".toString()
}
'Readable GString template toString' {
"${foo}${bar}${baz}".toString()
}
Agora temos os resultados:
String adder 514
GString template 267
Readable GString template 269
GString template toString 478
Readable GString template toString 480
StringBuilder 321
StringBuffer 369
Como você pode ver (como eu disse), é mais lento que StringBuilder ou StringBuffer, mas ainda um pouco mais rápido do que adicionar Strings ...
Mas ainda muito mais legível.
Editar após o comentário de ruralcoder abaixo
Atualizado para o gbench mais recente, strings maiores para concatenação e um teste com um StringBuilder inicializado com um bom tamanho:
@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()
dá
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()
anexo aos dois testes GString. Minha corrida mostra que eles têm quase o mesmo desempenhoString adder
. Meu palpite é que o teste que você executou não lida com a concatenação, então ele está apenas criando um objeto GString e armazenando as referências.StringBuilder
ainda é o mais rápido, sem dúvida, se você precisar de umString
em algum momento.GString
"como está", em algum ponto ele terá que ser convertido em verdadeiroString
(mesmo que apenas para imprimi-lo), então o tempo verdadeiro é o último conjunto. No final, a legibilidade dosGString
modelos bateStringBuilder
quando o tempo está próximo, então é discutível. :-)Não tenho certeza de por que a resposta acima precisa ir para benchmarks, buffers de string, testes, etc.
fonte
Reproduzindo a resposta tim_yates no hardware atual e adicionando os métodos leftShift () e concat () para verificar a descoberta:
O resultado mostra que concat () é a solução mais rápida para uma String pura, mas se você pode lidar com GString em outro lugar, o modelo GString ainda está à frente, enquanto a menção honrosa deve ir para leftShift () (operador bit a bit) e StringBuffer () com inicial alocação:
fonte