GUJ Discussões   :   últimos tópicos   |   categorias   |   GUJ Respostas

StringBuffer

Opa pessoal,

Uma dúvida, porque usar o StringBuffer?
Eu poderia fazer com o string dando um +=, mas vejo que o pessoal procura usar o StringBuffer.

Eu uso o StringBuffer, mas não sei o porque.

VELO

String nome = "andre"; nome += " programador"; nome += " java";

Isso é errado.
Fazendo assim, vc cria 3 espaços em memória, usando StringBuffer vc só usa um.
Concatenação é sempre mais “pesado”

StrinBuffer nome = new StringBuffer(); nome.append("andre"); nome.append(" programador"); nome.append(" java");

Assim vc só usou um espaço em memória :wink:

2 curtidas

[quote=andre_a_s][code]
Isso é errado.
Fazendo assim, vc cria 3 espaços em memória, usando StringBuffer vc só usa um.
Concatenação é sempre mais “pesado”
Assim vc só usou um espaço em memória ;)[/quote]

Ou seja, simplismente por questão de desempenho e boa prática. :stuck_out_tongue:

para ajudar na explicação. String é um tipo de dado IMUTÁVEL. ou seja, ele NUNCA muda. Para vc concatenar uma String a VM tem que criar uma segunda String para criar uma terceira(o resultado). Vamos ver um código para vc entender melhor

String s = "Java"; //Aqui ele cria uma String normal. IMUTAVEL s += "Free"; // Aqui é ciado uma String "Free". deposi disso é criado // uma terceira String com o valor "JavaFree". Tudo isso // A vm faz pra vc StringBuffer sb = new StringBuffer(); //MUTAVEL sb.append("Java");//apenas concatena o valor sb.append("Free");// aqui tb apenas conc

Usar StringBuffer é beeem mais rápido para concatenar grandes quantidades de String. faça um teste. coloque um for de 1milhão concatenando String com += e depois faça o mesmo usando StringBuffer

Para se convencer, rode isso aqui:

int loop = 100000;

StringBuffer sb = new StringBuffer();
long time = System.currentTimeMillis();
for( int i = 0; i < loop; i++ )
    sb.append( "a" );

System.out.println( "Tempo total de excecução com StringBuffer: " + ( System.currentTimeMillis() - time ) + "ms." );

String s = "";
time = System.currentTimeMillis();
for( int i = 0; i < loop; i++ )
    s += "a";

System.out.println( "Tempo total de excecução concatenando strings: " + ( System.currentTimeMillis() - time ) + "ms." );

Olá

Lembro que ao usar a atual versão do Java (5.0), se não for necessário ter sincronização nas threads, isto é, quando as Strings forem usadas em uma única thread de cada vez, se deve usar StringBuilder.

StringBuilder tem os mesmos métodos de StringBuffer mas não é sincronizada.

[]s
Luca

loop = 10000;

[quote]Tempo total de excecucao com StringBuffer: 0ms.
Tempo total de excecucao concatenando Strings: 903ms.[/quote]

Com loop = 50000 estou esperando o String até agora. O StringBuffer deu míseros 10ms.

<editado>
Opsss… terminou:

[quote]Tempo total de excecucao com StringBuffer: 10ms.
Tempo total de excecucao concatenando Strings: 62950ms.[/quote]
</editado>

O .NET Framework nesse ponto é igualzinho ao Java. Você tem a classe System.String (= java.lang.String) e a classe System.Text.StringBuilder (= java.lang.StringBuilder).
O comportamento é igualzinho, assim como a recomendação de usar StringBuffer (StringBuilder) sempre que possível. Não cheguei a ver o que o csc (compilador C#) gera para uma concatenação de strings com “+” ou “+=”, mas deve ser algo parecido com o que o Java faz (criar um objeto StringBuffer ou StringBuilder “por debaixo dos panos”.)

Beleza pessoal, valeu pela ajuda.

VELO

[quote=Luca]Olá

Lembro que ao usar a atual versão do Java (5.0), se não for necessário ter sincronização nas threads, isto é, quando as Strings forem usadas em uma única thread de cada vez, se deve usar StringBuilder.

StringBuilder tem os mesmos métodos de StringBuffer mas não é sincronizada.

[]s
Luca[/quote]

Testei esse cara… ele é exatamente o q vc falou, um xerox do StringBuffer mas sem a sincronização…

O StringBuilder realmente é um pouco mais rápido.

Para um loop de 5000000 :shock: :shock: :shock: :shock:

A diferença, na minha opinião, não justifica a criação do StringBuilder, q 6 axam?

VELO

Sou iniciante em java e gostaria de saber como eu faço pra excluir o conteúdo de uma StringBuffer

[quote=velo][quote=Luca]Olá

Lembro que ao usar a atual versão do Java (5.0), se não for necessário ter sincronização nas threads, isto é, quando as Strings forem usadas em uma única thread de cada vez, se deve usar StringBuilder.

StringBuilder tem os mesmos métodos de StringBuffer mas não é sincronizada.

[]s
Luca[/quote]

Testei esse cara… ele é exatamente o q vc falou, um xerox do StringBuffer mas sem a sincronização…

O StringBuilder realmente é um pouco mais rápido.

Para um loop de 5000000 :shock: :shock: :shock: :shock:

A diferença, na minha opinião, não justifica a criação do StringBuilder, q 6 axam?

VELO[/quote]

Dá uma olhada na documentação:
http://java.sun.com/j2se/1.4.2/docs/api/java/lang/StringBuffer.html#delete(int,%20int)

Aproveitando a discussao, o StringBuffer possui algum método q faca o mesmo q o split() ? q eu possa separar a String em substrings a partir de um delimitador?
nao encontrei nada do tipo e getRequestURL() só aceita StringBuffer, acabando com minha implementacao com o split().

Desde já obrigado.

outra questao é evitar objetos perdido… usando StringBuilder/Buffer. E isso é um conceito tb fundamental, além da questao do tempo de execucao que foi citada .

[quote=Filipe Sabella]Para se convencer, rode isso aqui:

[code]
int loop = 100000;

StringBuffer sb = new StringBuffer();
long time = System.currentTimeMillis();
for( int i = 0; i < loop; i++ )
sb.append( “a” );

System.out.println( "Tempo total de excecução com StringBuffer: " + ( System.currentTimeMillis() - time ) + “ms.” );

String s = “”;
time = System.currentTimeMillis();
for( int i = 0; i < loop; i++ )
s += “a”;

System.out.println( "Tempo total de excecução concatenando strings: " + ( System.currentTimeMillis() - time ) + “ms.” );
[/code][/quote]

Ola, tentei executar esse codigo e deu o seguinte erro:

O que aconteceu? O que eu fiz de errado?

[quote=schuelter]para ajudar na explicação. String é um tipo de dado IMUTÁVEL. ou seja, ele NUNCA muda. Para vc concatenar uma String a VM tem que criar uma segunda String para criar uma terceira(o resultado). Vamos ver um código para vc entender melhor

String s = "Java"; //Aqui ele cria uma String normal. IMUTAVEL s += "Free"; // Aqui é ciado uma String "Free". deposi disso é criado // uma terceira String com o valor "JavaFree". Tudo isso // A vm faz pra vc StringBuffer sb = new StringBuffer(); //MUTAVEL sb.append("Java");//apenas concatena o valor sb.append("Free");// aqui tb apenas conc

Usar StringBuffer é beeem mais rápido para concatenar grandes quantidades de String. faça um teste. coloque um for de 1milhão concatenando String com += e depois faça o mesmo usando StringBuffer[/quote]

Mesmo assim:
nesse Exemplo com String seriam criados 3 Objetos String.
E no StringBuffer tambêm…
O proprio Objeto String Buffer, e os Dois argumentos que são Objetos String tambêm… (“Java”) e (“Free”)
Qual é a explicação para isso ?

[quote=velo]Para um loop de 5000000 :shock: :shock: :shock: :shock:

A diferença, na minha opinião, não justifica a criação do StringBuilder, q 6 axam?[/quote]

A pergunta é… por que não justifica? A classe é idêntica, o código será idêntico e mais rápido. Além disso, são raríssimas as vezes que você vai precisar da sincronização do string buffer.
Na verdade, é justamente ao contrário. São poucas situações que justificam a criação de um StringBuffer.

Outra coisa, a diferença foi tão pequena porque você está rodando com uma única thread. A VM é esperta o suficiente para saber disso e eliminar boa parte do overhead de código envolvido na sincronização nesse caso, já que ela sabe que não haverá concorrência.

[quote=m4rkk]Mesmo assim:
nesse Exemplo com String seriam criados 3 Objetos String.
E no StringBuffer tambêm…
O proprio Objeto String Buffer, e os Dois argumentos que são Objetos String tambêm… (“Java”) e (“Free”)
Qual é a explicação para isso ?[/quote]

A diferença é que o custo de criação das strings literais é ínfimo, enquanto o custo de criação das strings em tempo de execução é alto.
Strings literais podem ser criadas e cacheadas em tempo de compilação.

Além do mais, a maior parte das situações em que faremos concatenações assim é de valores já alocados em memória, ou lidos de alguma fonte.
Aí formataremos uma nova String. Por isso o exemplo também não reflete uma situação real.

Mas claro, para um caso tão minusculo como o do exemplo, você dificilmente veria alguma diferença significativa de performance.
Agora, ponha concatenações num loop, e você observa rapidinho.

É issso aeeee!

Boa tarde galera,

Primeiramente eu queria parabenizá-los, pois este tópico está show de bola!!
Deu para entender direitinho o comportamento, os exemplos estão bem claros!

Tenho uma dúvida e gostaria de saber também a opinião de vocês.
No meu caso, em um programa que tenho que mexer, tem uma String que é concatenada umas 4 vezes, à grosso modo, é algo mais ou menos assim (bem a grosso modo, porque é bem pior que isso):

String filename = "ARQUIVO";
filename = filename + ".TXT"
filename = filename + ".GZIP";

Criei um StringBuffer (no meu caso estou usando Buffer, pois este programa é executado N vezes em paralelo) e coloquei estas informações com o método append.
Até aí tudo bem, mas em determinados momentos, eu preciso repassar o StringBuffer criado como parâmetro em alguns método, e acabo jogando um .toString() nele.

Neste caso, voltei a criar uma String na memória (além do StringBuffer já criado), com as mesmas características que vocês já falaram aqui (imutável, etc.)?
Alguém tem alguma sugestão ou comentário? No caso, eu repasso esse StringBuffer mais de uma vez, então passo a ter 2 Strings (com o mesmo valor) em memória?

Obs: os métodos são de JARs próprios da ferramenta que utilizo para programar, não há possibilidade de modificá-los…

Obrigado a todos, abs!!

//