Acabei de encontrar alguma construção de consulta sql como esta no meu projeto:
return (new StringBuilder("select id1, " + " id2 " + " from " + " table")).toString();
Isso StringBuilder
atinge seu objetivo, ou seja, reduzir o uso de memória?
Duvido, porque no construtor é usado o '+' (operador String concat). Isso consumirá a mesma quantidade de memória que usar String como o código abaixo? s eu entendi, ele difere durante o uso StringBuilder.append()
.
return "select id1, " + " id2 " + " from " + " table";
Ambas as instruções são iguais no uso de memória ou não? Por favor, esclareça.
Desde já, obrigado!
Editar:
BTW, não é meu código . Encontrei em um projeto antigo. Além disso, a consulta não é tão pequena quanto a do meu exemplo. :)
java
string
stringbuilder
Vaandu
fonte
fonte
PreparedStatement
ou algo semelhante: docs.oracle.com/javase/tutorial/jdbc/basics/prepared.htmlRespostas:
Não, de forma alguma. Esse código não está sendo usado
StringBuilder
corretamente. (Eu acho que você citou errado, entretanto; certamente não há aspasid2
etable
?)Observe que o objetivo (geralmente) é reduzir a rotatividade de memória em vez da memória total usada, para tornar a vida um pouco mais fácil para o coletor de lixo.
Não, isso causará mais rotatividade de memória do que apenas o concat direto que você citou. (Até / a menos que o otimizador JVM veja que o explícito
StringBuilder
no código é desnecessário e o otimize, se puder.)Se o autor desse código quiser usar
StringBuilder
(há argumentos a favor, mas também contra; consulte a nota no final desta resposta), melhor fazer isso corretamente (aqui estou assumindo que não há aspasid2
etable
):Observe que listei
some_appropriate_size
noStringBuilder
construtor, de forma que ele comece com capacidade suficiente para todo o conteúdo que iremos anexar. O tamanho padrão usado se você não especificar um é de 16 caracteres , que geralmente é muito pequeno e resulta naStringBuilder
necessidade de fazer realocações para se tornar maior (IIRC, no Sun / Oracle JDK, ele se duplica [ou mais, se sabe que precisa de mais para satisfazer um determinadoappend
] cada vez que fica sem espaço).Você pode ter ouvido que concatenação irá usar um
StringBuilder
debaixo das cobertas se compilado com o compilador Sun / Oracle. Isso é verdade, ele usará umStringBuilder
para a expressão geral. Mas ele usará o construtor padrão, o que significa que na maioria dos casos terá que fazer uma realocação. É mais fácil de ler, no entanto. Observe que isso não é verdade para uma série de concatenações. Então, por exemplo, ele usa umStringBuilder
:Isso se traduz aproximadamente em:
Então está tudo bem, embora o construtor padrão e as realocações subsequentes não sejam ideais, as chances são boas o suficiente - e a concatenação é muito mais legível.
Mas isso é apenas para uma única expressão. Vários
StringBuilder
s são usados para isso:Isso acaba se tornando algo assim:
... o que é muito feio.
É importante lembrar, porém, que em todos os casos , exceto em alguns casos , isso não importa e ir com a legibilidade (o que aumenta a capacidade de manutenção) é preferível, exceto um problema de desempenho específico.
fonte
x + y + z
expressão em vez de, aStringBuilder
menos que eu tivesse um bom motivo para suspeitar que seria um problema significativo.StringBuilder sql = new StringBuilder(" XXX); sql.append("nndmn");...
.sql.append
Linhas semelhantes têm cerca de 60 linhas. Esta bem?StringBuilder
inicialmente será alocado espaço suficiente para a string que você passou ao construtor mais 16 caracteres. Portanto, se você anexar mais de 16 caracteres (ouso dizer que sim, se houver 60 anexos!), OStringBuilder
terá que realocar pelo menos uma vez e possivelmente várias vezes. Se você tiver uma ideia razoável de quão grande será o resultado final (digamos, 400 caracteres), é melhor fazersql = new StringBuilder(400);
(ou o que quer que seja) do que fazer oappend
s.StringBuilder
isso com antecedência economizará cerca de oito realocações de memória (assumindo que a string inicial tinha cerca de 10 caracteres, o SB teria sido de 26 para começar, depois dobrado para 52, depois 104, 208, 416, 832, 1664, 3328 e finalmente 6656). Apenas significativo se for um ponto de acesso, mas ainda assim, se você souber com antecedência ... :-)Quando você já tem todas as "peças" que deseja acrescentar, não há sentido em usar
StringBuilder
. UsandoStringBuilder
e concatenação na mesma chamada de acordo com o seu código de amostra é ainda pior.Isso seria melhor:
Nesse caso, a concatenação de string está realmente acontecendo em tempo de compilação de qualquer maneira, então é equivalente ao ainda mais simples:
O uso
new StringBuilder().append("select id1, ").append(" id2 ")....toString()
realmente prejudicará o desempenho neste caso, porque força a concatenação a ser realizada em tempo de execução , em vez de em tempo de compilação . Opa.Se o código real está construindo uma consulta SQL incluindo valores na consulta, então esse é outro problema separado , que é que você deve usar consultas parametrizadas, especificando os valores nos parâmetros em vez de no SQL.
Eu tenho um artigo sobre
String
/StringBuffer
que escrevi há um tempo - antes deStringBuilder
aparecer. Os princípios se aplicamStringBuilder
da mesma forma.fonte
[[Existem algumas respostas boas aqui, mas acho que ainda faltam um pouco de informação. ]]
Como você indicou, o exemplo que você deu é simplista, mas vamos analisá-lo de qualquer maneira. O que acontece aqui é que o compilador realmente faz o
+
trabalho aqui porque"select id1, " + " id2 " + " from " + " table"
são todos constantes. Então, isso se transforma em:Nesse caso, obviamente, não adianta usar
StringBuilder
. Você também pode fazer:No entanto, mesmo se você estivesse anexando quaisquer campos ou outros não constantes, o compilador usaria um interno
StringBuilder
- não há necessidade de você definir um:Nos bastidores, isso se transforma em código que é aproximadamente equivalente a:
Realmente, a única vez que você precisa usar
StringBuilder
diretamente é quando você tem código condicional. Por exemplo, o código que se parece com o seguinte está desesperado por umStringBuilder
:O
+
na primeira linha usa umaStringBuilder
instância. Então o+=
usa outroStringBuilder
instância. É mais eficiente fazer:Outra vez que uso um
StringBuilder
é quando estou construindo uma string a partir de várias chamadas de método. Então, posso criar métodos que recebam umStringBuilder
argumento:Quando estiver usando um
StringBuilder
, você deve observar se há uso de+
ao mesmo tempo:Isso
+
vai causar outro internoStringBuilder
seja criado. Claro que deveria ser:Por fim, como @TJrowder aponta, você sempre deve tentar adivinhar o tamanho do
StringBuilder
. Isso economizará no número dechar[]
objetos criados ao aumentar o tamanho do buffer interno.fonte
Você está correto ao supor que o objetivo de usar o construtor de cordas não foi alcançado, pelo menos não em toda a sua extensão.
No entanto, quando o compilador vê a expressão,
"select id1, " + " id2 " + " from " + " table"
ele emite um código que, na verdade, cria umStringBuilder
segundo plano e o anexa, de modo que o resultado final não é tão ruim assim.Mas é claro que qualquer pessoa que olhar para esse código vai pensar que ele é meio retardado.
fonte
No código que você postou, não haveria vantagens, pois você está usando incorretamente o StringBuilder. Você constrói a mesma String em ambos os casos. Usando StringBuilder, você pode evitar a
+
operação em Strings usando oappend
método. Você deve usá-lo desta forma:Em Java, o tipo String é uma sequência inmutável de caracteres, portanto, quando você adiciona duas Strings, a VM cria um novo valor String com ambos os operandos concatenados.
StringBuilder fornece uma sequência mutável de caracteres, que você pode usar para conciliar diferentes valores ou variáveis sem criar novos objetos String e, portanto, às vezes pode ser mais eficiente do que trabalhar com strings
Isso fornece alguns recursos úteis, como alterar o conteúdo de uma sequência de caracteres passada como parâmetro dentro de outro método, o que você não pode fazer com Strings.
Mais informações em http://docs.oracle.com/javase/tutorial/java/data/buffers.html
fonte
+
, que será convertido no mesmo código de qualquer maneira.StringBuilder
é útil quando você não pode realizar toda a concatenação em uma única expressão, mas não neste caso.StringBuilder
se você fosse usarreturn "select id1, " + foo + "something else" + bar;
- então por que não fazer isso? A pergunta não fornece nenhuma indicação de que algo precisa ser divulgadoStringBuilder
.Você também pode usar MessageFormat demais
fonte