Atualizado: 26/07/2025

Este conteúdo é original e não foi gerado por inteligência artificial.

Strings Mutáveis: StringBuffer e StringBuilder em Java

O problema: a imutabilidade da String

Objetos da classe String são imutáveis. Isso significa que qualquer operação que pareça modificar uma string — como concatenar ou substituir caracteres — cria um novo objeto String na memória. Em cenários com muitas manipulações, como a construção de uma string longa dentro de um loop, isso pode gerar consumo excessivo de memória e queda de desempenho.


A solução: StringBuffer e StringBuilder

Para contornar esse problema, o Java oferece duas classes especializadas: StringBuffer e StringBuilder. Elas representam strings mutáveis, permitindo alterações no conteúdo sem criar um novo objeto a cada modificação.


A diferença principal: StringBuffer vs StringBuilder

As duas classes possuem a mesma API e construtores semelhantes. A diferença está na segurança em ambientes com múltiplas threads.

  • StringBuffer — métodos sincronizados, o que garante segurança em aplicações multithread. Isso impede que múltiplas threads alterem o mesmo objeto simultaneamente de forma insegura, mas adiciona sobrecarga e reduz um pouco a performance.
  • StringBuilder — não é sincronizado, o que o torna mais rápido. É a escolha recomendada na maioria dos casos, especialmente em aplicações de thread única.

Regra prática: Prefira StringBuilder pela performance, usando StringBuffer apenas se precisar manipular a mesma string em múltiplas threads.


Capacidade e comprimento

StringBuffer e StringBuilder usam um buffer interno — um array de caracteres que pode crescer quando necessário. Isso evita criar novos objetos a cada modificação.

  • Comprimento (length()) — número de caracteres que o conteúdo possui no momento.
  • Capacidade (capacity()) — tamanho máximo que o buffer pode armazenar antes de precisar crescer.

A capacidade inicial varia conforme a forma de criação:

Criando um StringBuilder vazio

Capacidade inicial padrão: 16 caracteres.

StringBuilder sbVazio = new StringBuilder();
System.out.println(sbVazio.length());   // 0
System.out.println(sbVazio.capacity()); // 16

Criando com texto inicial

Capacidade inicial: comprimento do texto + 16.

StringBuilder sb = new StringBuilder("Java");
System.out.println(sb.length());   // 4
System.out.println(sb.capacity()); // 20 (4 + 16)

Crescimento de capacidade

O método ensureCapacity() garante uma capacidade mínima. Se o valor informado for maior que a capacidade atual, o buffer cresce de acordo com a fórmula:

Exemplo:

StringBuilder sb = new StringBuilder("Java"); // capacidade inicial: 20
sb.ensureCapacity(32); // 20 < 32, precisa crescer
System.out.println(sb.capacity()); // 42 ((20 * 2) + 2)

Convertendo para String

Para obter um objeto String imutável, use toString():

StringBuilder sb = new StringBuilder("Hello");
String result = sb.toString();

Principais métodos

A maioria dos métodos modifica o próprio objeto em vez de criar um novo.

Adição e inserção

StringBuilder sb = new StringBuilder("Hello");
sb.append(" World"); // "Hello World"

StringBuilder sb2 = new StringBuilder("word");
sb2.insert(3, 'l'); // "world"

Remoção e substituição

StringBuilder sb = new StringBuilder("assembler");
sb.delete(0, 2);    // "sembler"
sb.deleteCharAt(6); // "semble"

StringBuilder sb2 = new StringBuilder("hello world!");
sb2.replace(6, 11, "java"); // "hello java!"

Outros métodos úteis

StringBuilder sb = new StringBuilder("reverter");
sb.reverse(); // "retrever"

StringBuilder sb2 = new StringBuilder("Java");
sb2.setCharAt(0, 'L'); // "Lava"

// substring() não altera o conteúdo original
StringBuilder sb3 = new StringBuilder("hello java!");
String part = sb3.substring(6); // "java!"

Tabela comparativa

CaracterísticaStringStringBufferStringBuilder
MutabilidadeImutávelMutávelMutável
PerformanceLenta para alteraçõesBoaExcelente
Thread-SafeSim (imutável)Sim (sincronizado)Não
Uso principalTexto fixoConstrução de strings em multithreadConstrução de strings em thread única (uso geral)

Resumo – Strings Mutáveis em Java

  • String é imutável; cada modificação cria um novo objeto.
  • StringBuffer e StringBuilder são mutáveis, permitindo alterações sem criar novos objetos.
  • StringBuffer é sincronizado e seguro em múltiplas threads, mas mais lento.
  • StringBuilder é não sincronizado, mais rápido e indicado para uso geral.
  • Ambos usam um buffer interno com capacidade ajustável.
  • Oferecem métodos como append(), insert(), delete(), replace(), reverse(), setCharAt() e substring().

📝 Exercícios

Tarefa 1 (Teoria)

Descrição: Um programador precisa concatenar 1.000 pequenas strings para formar uma única string longa dentro de um loop. Qual é a abordagem mais eficiente em termos de performance e por quê?

Alternativas:

  • Usar a classe String e o operador +, pois é o código mais simples de escrever.
  • Usar a classe StringBuilder e seu método append(), pois ela modifica a string internamente sem criar novos objetos a cada iteração.
  • Usar a classe StringBuffer, pois ela é sempre a opção mais rápida disponível.
Resposta

A resposta correta é: Usar a classe StringBuilder e seu método append(), pois ela modifica a string internamente sem criar novos objetos a cada iteração.

Explicação:

A classe String é imutável. Isso significa que a cada iteração do loop, a linha minhaString = minhaString + "nova_parte"; não modifica a string existente, mas cria um objeto String completamente novo na memória, contendo o resultado da concatenação. Para 1.000 iterações, isso resulta na criação de 1.000 objetos intermediários e um grande impacto negativo na performance.

Por outro lado, StringBuilder foi projetado para ser mutável. Seu método append() simplesmente adiciona os novos caracteres ao seu buffer interno, redimensionando-o apenas quando necessário. Isso evita a criação massiva de objetos, tornando-o a escolha ideal e muito mais eficiente para a construção de strings em loops.

Tarefa 2 (Prática)

Descrição: Complete o método montarUrl para que ele use um StringBuilder para construir e retornar uma URL a partir das partes fornecidas. A URL final deve ter o formato https://dominio.com/recurso?param=valor.

Código inicial:

public class Main {
    public static void main(String[] args) {
        String dominio = "dominio.com";
        String recurso = "recurso";
        String parametro = "param";
        String valor = "valor";

        String url = montarUrl(dominio, recurso, parametro, valor);
        System.out.println(url); // Resultado esperado: https://dominio.com/recurso?param=valor
    }

    static String montarUrl(String dominio, String recurso, String parametro, String valor) {
        // Use um StringBuilder para construir a URL eficientemente.
        // Retorne o resultado como uma String.

    }
}
Resposta

Solução:

public class Main {
    public static void main(String[] args) {
        String dominio = "dominio.com";
        String recurso = "recurso";
        String parametro = "param";
        String valor = "valor";

        String url = montarUrl(dominio, recurso, parametro, valor);
        System.out.println(url);
    }

    static String montarUrl(String dominio, String recurso, String parametro, String valor) {
        StringBuilder sb = new StringBuilder();
        sb.append("https://");
        sb.append(dominio);
        sb.append("/");
        sb.append(recurso);
        sb.append("?");
        sb.append(parametro);
        sb.append("=");
        sb.append(valor);

        return sb.toString();
    }
}

Explicação:

A solução cria um StringBuilder e utiliza o método append() repetidamente para adicionar cada parte da URL de forma eficiente, sem criar objetos String intermediários a cada passo. No final, o método toString() é chamado para converter o conteúdo mutável do StringBuilder em um único objeto String final, que é então retornado. Este é o caso de uso ideal para StringBuilder.

Política de Privacidade

Copyright © www.programicio.com Todos os direitos reservados

É proibida a reprodução do conteúdo desta página sem autorização prévia do autor.

Contato: programicio@gmail.com