Concatenação de Strings

6 respostas
douglasfs

No livro “Effective Java” do Joshua Block, na página 155, ele fala sobre a performance na concatenação de Strings, veja esse exemplo :

// Inappropriate use of string concatenation - Performs horribly !

public String statement() {
   String s = "";
   for (int i = 0; i < numItems(); i++)
      s += lineForItem(i); // String concatenation
   return s;

Daí ele fala para utilizar a classe StringBuffer e até comentou que na máquina dele utilizando o StringBuffer foi 90 vezes mais rápido.

public String statement() {
   StringBuffer s = new StringBuffer(numItems() * LINE_WIDTH);
   for (int i = 0; i < numItems(); i++)
      s.append(lineForItem(i)); // String concatenation
   return s.toString();

Nesse caso ele utilizou o JDK 1.3.

Eu estive vendo a classe StringBuffer na documentação do JDK 1.4.0 e lá diz :

String buffers are used by the compiler to implement the binary string concatenation operator +. For example, the code:

x = “a” + 4 + “c” is compiled to the equivalent of:
x = new StringBuffer().append(“a”).append(4).append(“c”).toString()

which creates a new string buffer (initially empty), appends the string representation of each operand to the string buffer in turn, and then converts the contents of the string buffer to a string. Overall, this avoids creating many temporary strings.

Estive vendo a documentação do JDK 1.3 e é a mesma coisa, será que a performance foi melhor porque ele alocou o StringBuffer com numItems() * LINE_WIDTH ?

O estranho é que ele nem comentou que a contatenação de Strings é implementada como um StringBuffer pelo compilador.

Ainda vou fazer o teste medindo o tempo com um StringBuffer com a alocação default e uma alocação definida pelo Joshua Block.

O que vocês acham ?

6 Respostas

F

Opa,

Num é bem assim q funciona cara. O problema de concatenar Strings, é que elas são imutáveis. Toda vez que se concatena uma String com outra, ela gera uma nova String. E por aí vai. Se vc concatenar muitas Strings, vai gerando muitos objetos na memória o que compromete a performance. A classe StringBuffer não é assim. Ela não gera novos objetos quando se chama o método append(). Ela realmente concatena no mesmo objeto. Por isso a performance dela é bem melhor e é altamente recomendável utilizar StringBuffer ao se fazer uso de concatenações.

maxguzenski

exatamente, strings sao imutaveis e StringBuffer sao mutaveis :slight_smile:

quer dizer cada “+” em string cria um objeto novo na memoria…
com StringBuffer isso nao acontece

concordo, que deveria estar escrito mais claramente isso na API…

dukejeffrie

O que o douglasfs falou não tem a ver com mutévei e imutáveis. Mas pensa assim, douglas: vc vai trocar todos os + por utilização de StringBuffer, certo? O que vc faz com +=??

// original:
s += s + lineForItem(i);
// vira:
s = new StringBuffer().append(s).append(lineForItem(i).toString();

Percebe que do mesmo jeito ele continua construindo várias Strings?
Triste, neh?? O problema é que fazer new é a operação proporcionalmente mais cara em Java.

Eu tive a oportunidade de ver um aumento de performance num código que montava uma query gigantesca com cada um de 18 parâmetros opcionais, sendo que se o parâmetro estava na ordem, ele aparecia no ORDER BY também. Troquei tudo pra StringBuffer e deu um ganho de mais ou menos 30% em qq query, 50% com todos os itens. Isso que o pesado era montar a saída, que tb ficou com StringBuffers.

Hj em dia eu uso StringBuffer até em msgs de debug. Virei maníaco… 8)

[]s

cv1

Espero que vc esteja brincando, Duke, pq não tem nada mais feio do que ver um monte de StringBuffer esparramado pelo código onde não acontece nenhum problema de performance. Leia a assinatura do Paulo Silveira de novo pra saber do que eu tou falando :slight_smile:

Aliás, parece que tem um assunto batendo forte no consciente coletivo do GUJ, que é a micro-otimização. Diacho, se vc tá trabalhando com EJBs, WebServices, CORBA e Struts, não vai ser um mero StringBuffer que vai resolver seu problema de performance. Um profiler bem usado vai, quem sabe, te dizer onde está o problema, não um javadoc da java.lang.StringBuffer :wink:

Bani

Uma explicação bem interessante do funcionamento da classe StringBuffer versus como os compiladores tratam a concatenação de Strings através do += foi dada na newsletter Java Specialists do mês passado. Há inclusive comparações de performance.
Quem quiser ler, pode acessar em http://www.javaspecialists.co.za/archive/Issue068.html
(Obs.: no momento em que estava escrevendo isso o link estava fora do ar, mas acho que qualquer hora volta…)

dukejeffrie

Claro, claro, to brincando!!!

Aconteceu uma vez de verdade e de lá pra cá eu fico brincando com isso…

Eu tb acho que a micro otimização é terrível… mas como em Java um programa típico é uma coleção de minúsculos métodos que não fazem quase nada, a tentação de deixar aquele pouco código é grande… mas eu lembro de um trabalho de IA que eu fiz na faculdade há algum tempo…

Era uma busca em uma arvore, e eu tinha um conjunto de nós já olhados. Como os nós em si não podiam ser pintados, eu tinha uma Collection com as opções, e o método equals era usado no processo pra dizer se elas eram equivalentes.

o equals era mesmo muito eficiente, pq eu tinha que utilizálo no código abaixo:

Collection olhados; // a tal collection
  ...
  protected void processaNoh(Noh novo) {
    if (olhados.contains(novo)) return;
    ... // processa de verdade o nó, gerando mais um monte de nós e colocando este nó entre os olhados.
  }

Eu sabia que o contains usava o equals, por isso fiquei olhando um tempão pra ele, pra fazê-lo o mais eficiente possível. Mas olha a cagada que eu tava fazendo em outro lugar:

olhados = new Vector();

Mesmo que fosse ArrayList, era com certeza a collection menos indicada pra isso. Acho que ainda não tinha saído o JDK 1.3, mas se não me engano já tinha Hashtable. Como era um projeto de IA, a gente nem se espantou com a lerdeza da coisa, só quando a gente viu os números de outros alunos (aliás, quem comentou sobre usar Hashmap foi o Paulo) que a gente viu o quanto foi inútil se preocupar com o equals.

aquelão!!!

Criado 20 de maio de 2003
Ultima resposta 21 de mai. de 2003
Respostas 6
Participantes 6