Outra pergunta: por que você usa um SB apenas para uma iteração do loop? Existe outra iteração interna? O SB não vale a pena se você simplesmente deseja fazer A + B + C + D (o compilador Java usará internamente um SB). Ajuda se você deseja adicionar condicionalmente partes de strings, mas caso contrário ... basta usar "+".
helios
Respostas:
135
Uma opção é usar o método delete da seguinte maneira:
StringBuffer sb =newStringBuffer();for(int n =0; n <10; n++){
sb.append("a");// This will clear the buffer
sb.delete(0, sb.length());}
Outra opção (limpador de bits) usa setLength (int len) :
Algo um pouco menos inútil seria apenas declarar o StringBuffer dentro do loop.
Mark Elliot
11
Ah, acho que sb.setLength (0); é mais limpo e mais eficiente do que declará-lo dentro do loop. Sua solução vai contra o benefício de usar StringBuffer desempenho ...
Jon
6
Eu acho que o benefício de desempenho vem da mutabilidade de string, não de salvar a instanciação. aqui está um teste rápido de 1E8 iterações: loop dentro (2.97s): ideone.com/uyyTL14w , laço exterior (2.87s): ideone.com/F9lgsIxh
Mark Elliot
6
Falando em desempenho: a menos que seu código seja acessado em um cenário multithread, você deve usar StringBuilder em vez de StringBuffer - consulte javadoc: "Onde possível, é recomendável que essa classe seja usada preferencialmente a StringBuffer, pois será mais rápido em maioria das implementações ".
Rahel Lüthy
4
O único benefício de criar o SB externo não é perder o caráter interno (potencialmente longo) [] dele. Se no primeiro iterador crescer o suficiente, o segundo loop não precisará redimensionar nenhum caractere []. Mas, para obter a vantagem, o "método claro" precisará preservar o tamanho da matriz interna. setLength faz isso, mas também define para \ u0000 todos os caracteres não usados no SB, por isso é menos eficiente do que simplesmente criar um novo SB com uma boa capacidade inicial. Declarar dentro do loop é melhor.
helios
48
A maneira mais fácil de reutilizar o StringBufferé usar o métodosetLength()
sb.setLength(0);// It will just discard the previous data, which will be garbage collected later.
Ou use:
sb.delete(0, sb.length());// A bit slower as it is used to delete sub sequence.
NOTA
Evite declarar StringBufferou StringBuilderobjetos dentro do loop, caso contrário, ele criará novos objetos a cada iteração. A criação de objetos requer recursos do sistema, espaço e também leva tempo. Portanto, a longo prazo, evite declará-los em um loop, se possível.
Sugiro criar um novo StringBuffer(ou até melhor StringBuilder) para cada iteração. A diferença de desempenho é realmente insignificante, mas seu código será mais curto e mais simples.
Se você tiver alguma evidência dessa diferença de desempenho, compartilhe-a. (Eu estarei também contente de ver estatísticas de onde Java é utilizado, principalmente, e em que a definição de "principalmente".)
Eli Acherkan
1
É sabido que a alocação (nova palavra-chave em Java) é mais cara do que apenas alterar alguns campos do mesmo objeto. Para "principalmente", com o qual você poderia substituir muito, existem mais de 1,5 bilhão de dispositivos Android, todos usando Java.
Louis CAD
1
Concordo que, em alguns casos, a legibilidade do código é mais importante que o desempenho, mas, neste caso, é apenas uma linha de código! E você pode executar uma referência que provará que a alocação e a criação de objetos, além da coleta de lixo, são mais caras do que não serem realizadas. Como estamos em um loop, é mais do que relevante.
Louis CAD,
1
Também subscrevi a visão de Knuth, mas seu ponto de vista nem sempre é verdadeiro. Adicionar apenas uma linha para potencialmente ganhar ciclos de CPU e memória não é absolutamente ruim. Você está levando a idéia muito a sério. Observe que um loop geralmente é repetido várias vezes. Um loop pode ser repetido milhares de vezes, que pode consumir megabytes preciosos em um celular (e também em um servidor ou computador) se não for otimizado com cuidado.
Louis CAD,
1
Penso que ambos declarámos os nossos pontos de vista com clareza suficiente e considero que uma discussão mais aprofundada não será benéfica para esta secção de comentários. Se você acha que minha resposta é incorreta, enganosa ou incompleta, você - ou qualquer pessoa - é bem-vinda para editá-la e / ou votá-la.
Já boa resposta lá. Basta adicionar um resultado de benchmark para que a diferença de desempenho StringBuffer e StringBuild use nova instância no loop ou use setLength (0) no loop.
O resumo é: Em um loop grande
StringBuilder é muito mais rápido que StringBuffer
Criar nova instância StringBuilder em loop não tem diferença com setLength (0). (setLength (0) tem uma vantagem muito, muito pequena, do que criar uma nova instância.)
StringBuffer é mais lento que StringBuilder ao criar nova instância no loop
setLength (0) de StringBuffer é extremamente mais lento que criar uma nova instância em loop.
Referência muito simples (eu mudei manualmente o código e fiz testes diferentes):
publicclassStringBuilderSpeed{publicstaticfinalchar ch[]=newchar[]{'a','b','c','d','e','f','g','h','i'};publicstaticvoid main(String a[]){int loopTime =99999999;long startTime =System.currentTimeMillis();StringBuilder sb =newStringBuilder();for(int i =0; i < loopTime; i++){for(char c : ch){
sb.append(c);}
sb.setLength(0);}long endTime =System.currentTimeMillis();System.out.println("Time cost: "+(endTime - startTime));}
}
Nova instância StringBuilder em loop: Custo do tempo: 3693, 3862, 3624, 3742
StringBuilder setLength: Custo do tempo: 3465, 3421, 3557, 3408
Nova instância StringBuffer no loop: Custo do tempo: 8327, 8324, 8284
StringBuffer setLength Custo de tempo: 22878, 23017, 22894
Novamente StringBuilder setLength para garantir que meu labtop não tenha problemas para usar tanto tempo como StringBuffer setLength :-) Custo de tempo: 3448
Respostas:
Uma opção é usar o método delete da seguinte maneira:
Outra opção (limpador de bits) usa setLength (int len) :
Veja Javadoc para mais informações:
fonte
A maneira mais fácil de reutilizar o
StringBuffer
é usar o métodosetLength()
public void setLength(int newLength)
Você pode ter o caso como
fonte
setLength
vez desetlength
.Você tem duas opções:
Ou use:
Ou use:
NOTA
Evite declarar
StringBuffer
ouStringBuilder
objetos dentro do loop, caso contrário, ele criará novos objetos a cada iteração. A criação de objetos requer recursos do sistema, espaço e também leva tempo. Portanto, a longo prazo, evite declará-los em um loop, se possível.fonte
fonte
Sugiro criar um novo
StringBuffer
(ou até melhorStringBuilder
) para cada iteração. A diferença de desempenho é realmente insignificante, mas seu código será mais curto e mais simples.fonte
Uso:
para facilitar a leitura, acho que essa é a melhor solução.
fonte
Já boa resposta lá. Basta adicionar um resultado de benchmark para que a diferença de desempenho StringBuffer e StringBuild use nova instância no loop ou use setLength (0) no loop.
O resumo é: Em um loop grande
Referência muito simples (eu mudei manualmente o código e fiz testes diferentes):
}
Nova instância StringBuilder em loop: Custo do tempo: 3693, 3862, 3624, 3742
StringBuilder setLength: Custo do tempo: 3465, 3421, 3557, 3408
Nova instância StringBuffer no loop: Custo do tempo: 8327, 8324, 8284
StringBuffer setLength Custo de tempo: 22878, 23017, 22894
Novamente StringBuilder setLength para garantir que meu labtop não tenha problemas para usar tanto tempo como StringBuffer setLength :-) Custo de tempo: 3448
fonte
Eu acho que esse código é mais rápido.
fonte