Diferença entre StringBuilder e StringBuffer
-
21-08-2019 - |
Pergunta
Qual é a principal diferença entre StringBuffer
e StringBuilder
? Há algum problema de desempenho ao decidir sobre qualquer um deles?
Solução
StringBuffer
é sincronizado, StringBuilder
não é.
Outras dicas
StringBuilder
é mais rápido que StringBuffer
Porque não é synchronized
.
Aqui está um teste de referência simples:
public class Main {
public static void main(String[] args) {
int N = 77777777;
long t;
{
StringBuffer sb = new StringBuffer();
t = System.currentTimeMillis();
for (int i = N; i --> 0 ;) {
sb.append("");
}
System.out.println(System.currentTimeMillis() - t);
}
{
StringBuilder sb = new StringBuilder();
t = System.currentTimeMillis();
for (int i = N; i > 0 ; i--) {
sb.append("");
}
System.out.println(System.currentTimeMillis() - t);
}
}
}
UMA execução de teste dá o número de 2241 ms
por StringBuffer
vs. 753 ms
por StringBuilder
.
Basicamente, StringBuffer
Os métodos são sincronizados enquanto StringBuilder
não são.
As operações são "quase" iguais, mas o uso de métodos sincronizados em um único encadeamento é um exagero.
Isso é praticamente sobre isso.
Citação do Stringbuilder API:
Esta classe [StringBuilder] fornece uma API compatível com StringBuffer, mas sem garantia de sincronização. Esta classe foi projetada para uso como substituição do StringBuffer em locais onde o buffer de string estava sendo usado por um único encadeamento (como geralmente é o caso). Sempre que possível, é recomendável que esta classe seja usada em preferência ao StringBuffer como Será mais rápido na maioria das implementações.
Por isso, foi feito para substituí -lo.
O mesmo aconteceu com Vector
e ArrayList
.
Mas precisava obter a diferença clara com a ajuda de um exemplo?
StringBuffer ou StringBuilder
Simplesmente use StringBuilder
A menos que você realmente esteja tentando compartilhar um buffer entre os threads. StringBuilder
é o irmão mais novo não sincronizado (menos sobrecarga = mais eficiente) do sincronizado original StringBuffer
classe.
StringBuffer
veio primeiro. O Sun estava preocupado com a correção em todas as condições, então eles o tornaram sincronizado para torná-lo seguro de linha apenas por precaução.
StringBuilder
veio depois. A maioria dos usos de StringBuffer
eram de fibra única e pagando desnecessariamente o custo da sincronização.
Desde StringBuilder
é um Substituição de entrega por StringBuffer
Sem a sincronização, não haveria diferenças entre nenhum exemplo.
Se você são tentando compartilhar entre threads, você pode usar StringBuffer
, mas considere se a sincronização de nível superior é necessária, por exemplo, talvez em vez de usar o StringBuffer, se você sincronizar os métodos que usam o StringBuilder.
Primeiro vamos ver o semelhanças: Tanto o StringBuilder quanto o StringBuffer são mutáveis. Isso significa que você pode alterar o conteúdo deles, com o mesmo local.
Diferenças: StringBuffer é mutável e sincronizado também. Onde o StringBuilder é mutável, mas não sincronizado por padrão.
Significado de sincronizado (sincronização): Quando alguma coisa é sincronizada, vários threads podem acessar e modificá -lo sem qualquer problema ou efeito colateral. O StringBuffer é sincronizado, para que você possa usá -lo com vários threads sem qualquer problema.
Qual usa quando?StringBuilder: quando você precisa de uma string, que pode ser modificável, e apenas um thread está acessando e modificando -o. StringBuffer: quando você precisa de uma string, que pode ser modificável, e vários threads estão acessando e modificando.
Observação : Não use o StringBuffer desnecessariamente, ou seja, não o use se apenas um thread estiver modificando e acessando -o, pois possui muito código de bloqueio e desbloqueio para sincronização, o que levará desnecessariamente o tempo da CPU. Não use bloqueios, a menos que seja necessário.
Em tópicos únicos, StringBuffer não é significativamente mais lento que o StringBuilder, graças às otimizações da JVM. E no multithreading, você não pode usar com segurança um StringBuilder.
Aqui está o meu teste (não uma referência, apenas um teste):
public static void main(String[] args) {
String withString ="";
long t0 = System.currentTimeMillis();
for (int i = 0 ; i < 100000; i++){
withString+="some string";
}
System.out.println("strings:" + (System.currentTimeMillis() - t0));
t0 = System.currentTimeMillis();
StringBuffer buf = new StringBuffer();
for (int i = 0 ; i < 100000; i++){
buf.append("some string");
}
System.out.println("Buffers : "+(System.currentTimeMillis() - t0));
t0 = System.currentTimeMillis();
StringBuilder building = new StringBuilder();
for (int i = 0 ; i < 100000; i++){
building.append("some string");
}
System.out.println("Builder : "+(System.currentTimeMillis() - t0));
}
Resultados :
Strings: 319740
Buffers: 23
Construtor: 7!
Portanto, os construtores são mais rápidos que os buffers e muito mais rápido que a concatenação de cordas. Agora vamos usar um Executor Para vários tópicos:
public class StringsPerf {
public static void main(String[] args) {
ThreadPoolExecutor executorService = (ThreadPoolExecutor) Executors.newFixedThreadPool(10);
//With Buffer
StringBuffer buffer = new StringBuffer();
for (int i = 0 ; i < 10; i++){
executorService.execute(new AppendableRunnable(buffer));
}
shutdownAndAwaitTermination(executorService);
System.out.println(" Thread Buffer : "+ AppendableRunnable.time);
//With Builder
AppendableRunnable.time = 0;
executorService = (ThreadPoolExecutor) Executors.newFixedThreadPool(10);
StringBuilder builder = new StringBuilder();
for (int i = 0 ; i < 10; i++){
executorService.execute(new AppendableRunnable(builder));
}
shutdownAndAwaitTermination(executorService);
System.out.println(" Thread Builder: "+ AppendableRunnable.time);
}
static void shutdownAndAwaitTermination(ExecutorService pool) {
pool.shutdown(); // code reduced from Official Javadoc for Executors
try {
if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
pool.shutdownNow();
if (!pool.awaitTermination(60, TimeUnit.SECONDS))
System.err.println("Pool did not terminate");
}
} catch (Exception e) {}
}
}
class AppendableRunnable<T extends Appendable> implements Runnable {
static long time = 0;
T appendable;
public AppendableRunnable(T appendable){
this.appendable = appendable;
}
@Override
public void run(){
long t0 = System.currentTimeMillis();
for (int j = 0 ; j < 10000 ; j++){
try {
appendable.append("some string");
} catch (IOException e) {}
}
time+=(System.currentTimeMillis() - t0);
}
}
Agora StringBuffers tomam 157 ms para 100000 apêndios. Não é o mesmo teste, mas comparado aos 37 ms anteriores, você pode assumir com segurança que Os prendedores de stringbuffers são mais lentos com o uso multithreading. O motivo é que o JIT/Hotspot/Compilador/Something faz otimizações quando detecta que existe não Necessidade de verificação de bloqueios.
Mas Com StringBuilder, você tem java.lang.arrayIndexoutOfBoundSexception, porque um fio simultâneo tenta adicionar algo onde não deveria.
Conclusão é que você não precisa perseguir stringbuffers. E onde você tem tópicos, pense no que eles estão fazendo, antes de tentar ganhar alguns nanossegundos.
O StringBuilder foi introduzido no Java 1.5 para que não funcione com o JVMS anterior.
De Javadocs:
A classe StringBuilder fornece uma API compatível com StringBuffer, mas sem garantia de sincronização. Esta classe foi projetada para uso como substituição do StringBuffer em locais onde o buffer de string estava sendo usado por um único encadeamento (como geralmente é o caso). Sempre que possível, é recomendável que esta classe seja usada em preferência ao StringBuffer, pois será mais rápido na maioria das implementações.
Muito boa pergunta
Aqui estão as diferenças, notei:
StringBuffer:-
StringBuffer is synchronized
StringBuffer is thread-safe
StringBuffer is slow (try to write a sample program and execute it, it will take more time than StringBuilder)
StringBuilder:-
StringBuilder is not synchronized
StringBuilder is not thread-safe
StringBuilder performance is better than StringBuffer.
Coisa comum :-
Ambos têm os mesmos métodos com as mesmas assinaturas. Ambos são mutáveis.
StringBuilder não é seguro. Buffer de string é. Mais informações aqui.
Editar: Quanto ao desempenho, depois ponto de acesso Inicia, o StringBuilder é o vencedor. No entanto, para pequenas iterações, a diferença de desempenho é insignificante.
StringBuilder
e StringBuffer
são quase iguais. A diferença é que StringBuffer
é sincronizado e StringBuilder
não é. Embora, StringBuilder
é mais rápido que StringBuffer
, a diferença no desempenho é muito pouco. StringBuilder
é a substituição do sol de StringBuffer
. Ele apenas evita a sincronização de todos os métodos públicos. Em vez disso, sua funcionalidade é a mesma.
Exemplo de bom uso:
Se o seu texto vai mudar e for usado por vários tópicos, é melhor usar StringBuffer
. Se o seu texto vai mudar, mas for usado por um único tópico, use StringBuilder
.
StringBuffer
- Sincronizado, portanto, ThreadSafe
- Thread seguro, portanto, lento
StringBuilder
- Introduzido em Java 5.0
- Assíncrono, portanto, rápido e eficiente
- O usuário precisa explicitamente sincronizá -lo, se ele quiser
- Você pode substituí -lo por
StringBuffer
Sem outra mudança
StringBuffer
StringBuffer é mutável significa que se pode alterar o valor do objeto. O objeto criado através do StringBuffer é armazenado na pilha. O StringBuffer possui os mesmos métodos que o StringBuilder, mas cada método no StringBuffer é sincronizado que é o StringBuffer é seguro.
Por esse motivo, não permite que dois threads acessem simultaneamente o mesmo método. Cada método pode ser acessado por um thread por vez.
Mas ser seguro para threads também tem desvantagens, pois o desempenho dos stringbuffer ocorre devido à propriedade segura do Thread. Assim, o StringBuilder é mais rápido que o StringBuffer ao chamar os mesmos métodos de cada classe.
O valor do StringBuffer pode ser alterado, significa que pode ser atribuído ao novo valor. Atualmente, é uma questão de entrevista mais comum, as diferenças entre as classes acima. O buffer de string pode ser convertido na sequência usando o método tostring ().
StringBuffer demo1 = new StringBuffer(“Hello”) ;
// The above object stored in heap and its value can be changed .
demo1=new StringBuffer(“Bye”);
// Above statement is right as it modifies the value which is allowed in the StringBuffer
StringBuilder
O StringBuilder é o mesmo que o StringBuffer, ou seja, armazena o objeto em heap e também pode ser modificado. A principal diferença entre o StringBuffer e o StringBuilder é que o StringBuilder também não é seguro. O StringBuilder é rápido, pois não é seguro.
StringBuilder demo2= new StringBuilder(“Hello”);
// The above object too is stored in the heap and its value can be modified
demo2=new StringBuilder(“Bye”);
// Above statement is right as it modifies the value which is allowed in the StringBuilder
String
é um imutável.
StringBuffer
é um mutável e sincronizado.
StringBuilder
também é mutável, mas não é sincronizado.
o Javadoc explica a diferença:
Esta classe fornece uma API compatível com StringBuffer, mas sem garantia de sincronização. Esta classe foi projetada para uso como substituição do StringBuffer em locais onde o buffer de string estava sendo usado por um único encadeamento (como geralmente é o caso). Sempre que possível, é recomendável que esta classe seja usada em preferência ao StringBuffer, pois será mais rápido na maioria das implementações.
StringBuilder
(introduzido em Java 5) é idêntico a StringBuffer
, exceto que seus métodos não são sincronizados. Isso significa que ele tem melhor desempenho que o último, mas a desvantagem é que não é segura por threads.
Ler tutorial para mais detalhes.
Um programa simples que ilustra a diferença entre StringBuffer e StringBuilder:
/**
* Run this program a couple of times. We see that the StringBuilder does not
* give us reliable results because its methods are not thread-safe as compared
* to StringBuffer.
*
* For example, the single append in StringBuffer is thread-safe, i.e.
* only one thread can call append() at any time and would finish writing
* back to memory one at a time. In contrast, the append() in the StringBuilder
* class can be called concurrently by many threads, so the final size of the
* StringBuilder is sometimes less than expected.
*
*/
public class StringBufferVSStringBuilder {
public static void main(String[] args) throws InterruptedException {
int n = 10;
//*************************String Builder Test*******************************//
StringBuilder sb = new StringBuilder();
StringBuilderTest[] builderThreads = new StringBuilderTest[n];
for (int i = 0; i < n; i++) {
builderThreads[i] = new StringBuilderTest(sb);
}
for (int i = 0; i < n; i++) {
builderThreads[i].start();
}
for (int i = 0; i < n; i++) {
builderThreads[i].join();
}
System.out.println("StringBuilderTest: Expected result is 1000; got " + sb.length());
//*************************String Buffer Test*******************************//
StringBuffer sb2 = new StringBuffer();
StringBufferTest[] bufferThreads = new StringBufferTest[n];
for (int i = 0; i < n; i++) {
bufferThreads[i] = new StringBufferTest(sb2);
}
for (int i = 0; i < n; i++) {
bufferThreads[i].start();
}
for (int i = 0; i < n; i++) {
bufferThreads[i].join();
}
System.out.println("StringBufferTest: Expected result is 1000; got " + sb2.length());
}
}
// Every run would attempt to append 100 "A"s to the StringBuilder.
class StringBuilderTest extends Thread {
StringBuilder sb;
public StringBuilderTest (StringBuilder sb) {
this.sb = sb;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
sb.append("A");
}
}
}
//Every run would attempt to append 100 "A"s to the StringBuffer.
class StringBufferTest extends Thread {
StringBuffer sb2;
public StringBufferTest (StringBuffer sb2) {
this.sb2 = sb2;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
sb2.append("A");
}
}
}
Use melhor o StringBuilder, pois não é sincronizado e, portanto, é melhor desempenho. StringBuilder é uma substituição do stringbuffer mais antigo.
StringBuffer
é sincronizado, mas StringBuilder
não é. Como resultado, StringBuilder
é mais rápido que StringBuffer
.
StringBufferé mutável. Pode mudar em termos de comprimento e conteúdo. Os StringBuffers são seguros para threads, o que significa que eles têm métodos sincronizados para controlar o acesso, para que apenas um thread possa acessar o código sincronizado de um objeto StringBuffer por vez. Assim, os objetos StringBuffer geralmente são seguros para usar em um ambiente multithread, onde vários threads podem estar tentando acessar o mesmo objeto StringBuffer ao mesmo tempo.
StringBuilderA classe StringBuilder é muito semelhante ao StringBuffer, exceto que seu acesso não é sincronizado para que não seja seguro para threads. Por não ser sincronizado, o desempenho do StringBuilder pode ser melhor que o StringBuffer. Assim, se você estiver trabalhando em um ambiente de thread único, o uso do StringBuilder em vez do StringBuffer pode resultar em maior desempenho. Isso também se aplica a outras situações, como uma variável local de StringBuilder (ou seja, uma variável dentro de um método) em que apenas um thread estará acessando um objeto StringBuilder.
StringBuffer:
- Multi fio
- Sincronizado
- Lento que StringBuilder
StringBuilder
- Único thread
- Não sincronizado
- Mais rápido do que nunca corda
String-Builder :
int one = 1;
String color = "red";
StringBuilder sb = new StringBuilder();
sb.append("One=").append(one).append(", Color=").append(color).append('\n');
System.out.print(sb);
// Prints "One=1, Colour=red" followed by an ASCII newline.
Buffer de cordas
StringBuffer sBuffer = new StringBuffer("test");
sBuffer.append(" String Buffer");
System.out.println(sBuffer);
Recomenda -se usar o StringBuilder sempre que possível, porque é mais rápido que o StringBuffer. No entanto, se a segurança do encadeamento for necessária, a melhor opção são os objetos StringBuffer.
O StringBuffer é usado para armazenar strings de caracteres que serão alterados (os objetos da string não podem ser alterados). Ele se expande automaticamente conforme necessário. Classes relacionadas: String, Charsequence.
O StringBuilder foi adicionado no Java 5. É idêntico em todos os aspectos ao StringBuffer, exceto que não é sincronizado, o que significa que, se vários threads o estiverem acessando ao mesmo tempo, pode haver problemas. Para programas de thread único, o caso mais comum, evitar a sobrecarga da sincronização torna o StringBuilder muito um pouco mais rápido.
Não há diferenças básicas entre StringBuilder e StringBuffer, existem apenas algumas diferenças entre elas. No StringBuffer, os métodos são sincronizados. Isso significa que, em um momento, apenas um tópico pode operar neles. Se houver mais de um thread, o segundo thread terá que esperar o primeiro terminar e o terceiro terá que esperar o primeiro e o segundo terminar e assim por diante. Isso torna o processo muito lento e, portanto, o desempenho no caso de StringBuffer é baixo.
Por outro lado, o StringBuilder não é sincronizado. Isso significa que, em um momento, vários threads podem operar no mesmo objeto StrinBuilder ao mesmo tempo. Isso torna o processo muito rápido e, portanto, o desempenho do StringBuilder é alto.
Desde StringBuffer
é sincronizado, ele precisa de algum esforço extra, portanto, com base no desempenho, é um pouco lento do que StringBuilder
.
String é um objeto imutável, o que significa que o valor não pode ser alterado onde o StringBuffer é mutável.
O StringBuffer é sincronizado, portanto, o thread segura, onde o StringBuilder não é e adequado apenas para instâncias de rosca única.
A principal diferença é StringBuffer
é sincronizado, mas StringBuilder
não é. StringBuilder
é mais rápido que StringBuffer
, porque não é sincronizado.
Verifique os internos do método de anexo sincronizado de StringBuffer
e método de apêmea não sincronizado de StringBuilder
.
public StringBuffer(String str) {
super(str.length() + 16);
append(str);
}
public synchronized StringBuffer append(Object obj) {
super.append(String.valueOf(obj));
return this;
}
public synchronized StringBuffer append(String str) {
super.append(str);
return this;
}
public StringBuilder(String str) {
super(str.length() + 16);
append(str);
}
public StringBuilder append(Object obj) {
return append(String.valueOf(obj));
}
public StringBuilder append(String str) {
super.append(str);
return this;
}
Já que o append é synchronized
, StringBuffer
tem sobrecarga de desempenho em comparação com StrinbBuilder
no cenário de threading. Contanto que você não esteja compartilhando buffer entre vários tópicos, use StringBuilder
, que é rápido devido à ausência de synchronized
nos métodos de anexo.
Aqui está o resultado do teste de desempenho para String vs StringBuffer vs StringBuilder. Finalmente, o StringBuilder venceu o teste. Veja abaixo o código de teste e o resultado.
Código:
private static void performanceTestStringVsStringbuffereVsStringBuilder() {
// String vs StringBiffer vs StringBuilder performance Test
int loop = 100000;
long start = 0;
// String
String str = null;
start = System.currentTimeMillis();
for (int i = 1; i <= loop; i++) {
str += i + "test";
}
System.out.println("String - " + (System.currentTimeMillis() - start) + " ms");
// String buffer
StringBuffer sbuffer = new StringBuffer();
start = System.currentTimeMillis();
for (int i = 1; i <= loop; i++) {
sbuffer.append(i).append("test");
}
System.out.println("String Buffer - " + (System.currentTimeMillis() - start) + " ms");
// String builder
start = System.currentTimeMillis();
StringBuilder sbuilder = new StringBuilder();
for (int i = 1; i <= loop; i++) {
sbuffer.append(i).append("test");
}
System.out.println("String Builder - " + (System.currentTimeMillis() - start) + " ms");
}
Resultado:
100000 iteração para adicionar um único texto
String - 37489 ms
String Buffer - 5 ms
String Builder - 4 ms
10000 iteração para adicionar um único texto
String - 389 ms
String Buffer - 1 ms
String Builder - 1 ms
- O StringBuffer é seguro para thread, mas o StringBuilder não é seguro.
- StringBuilder é mais rápido que o StringBuffer.
- O StringBuffer é sincronizado enquanto o StringBuilder não é sincronizado.
Todo método presente no StringBuffer é sincronizado. Portanto, em um momento, apenas um thread pode operar o objeto StringBuffer. Aumenta o tempo de espera de um thread e cria problemas de desempenho para superar esse problema que as pessoas da Sun intodiam o StringBuilder na versão 1.5.