Pergunta

Qual é a principal diferença entre StringBuffer e StringBuilder? Há algum problema de desempenho ao decidir sobre qualquer um deles?

Foi útil?

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

enter image description here

Recurso: String vs StringBuffer vs 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.

StringBuffer:

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;
}

StringBuilder:

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");

  }

Execute -me em ideone

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top