Respostas:
Diferença de mutabilidade:
String
é imutável , se você tentar alterar seus valores, um outro objeto é criado, enquanto StringBuffer
e StringBuilder
são mutáveis assim que podem mudar seus valores.
Diferença de segurança da linha:
A diferença entre StringBuffer
e StringBuilder
é que StringBuffer
é seguro para threads. Portanto, quando o aplicativo precisar ser executado apenas em um único encadeamento, é melhor usá-lo StringBuilder
. StringBuilder
é mais eficiente que StringBuffer
.
Situações:
String
objeto é imutável.StringBuilder
é bom o suficiente.StringBuffer
porque StringBuffer
é síncrona para que você tenha segurança de thread.Strings
quando alteramos o valor, outro objeto é criado. A referência de objeto antigo é anulada para que possa ser coletada pelo lixo GC
ou até mesmo coletada?
String
com StringBuilder
?
String
quando uma estrutura imutável é apropriada; obter uma nova sequência de caracteres de a String
pode levar a uma penalidade de desempenho inaceitável, seja no tempo ou na memória da CPU (a obtenção de substrings é eficiente na CPU porque os dados não são copiados, mas isso significa que uma quantidade potencialmente muito maior de dados pode permanecer alocada).StringBuilder
quando precisa criar uma sequência de caracteres mutável, geralmente para concatenar várias seqüências de caracteres juntas.StringBuffer
nas mesmas circunstâncias que usaria StringBuilder
, mas quando alterações na cadeia subjacente devem ser sincronizadas (porque vários segmentos estão lendo / modificando no buffer da cadeia).Veja um exemplo aqui .
O básico:
String
é uma classe imutável, não pode ser alterada.
StringBuilder
é uma classe mutável que pode ser anexada, caracteres substituídos ou removidos e, finalmente, convertidos em a String
StringBuffer
é a versão sincronizada original deStringBuilder
Você deve preferir StringBuilder
em todos os casos em que apenas um único thread acesse seu objeto.
Os detalhes:
Observe também que StringBuilder/Buffers
não é mágico, eles apenas usam uma matriz como um objeto de apoio e que a matriz precisa ser realocada sempre que ficar cheia. Certifique-se de criar seus StringBuilder/Buffer
objetos suficientemente grandes originalmente, onde eles não precisem ser constantemente redimensionados toda vez que forem .append()
chamados.
O redimensionamento pode ficar muito degenerado. Basicamente, redimensiona a Matriz de apoio para 2 vezes seu tamanho atual sempre que precisar ser expandida. Isso pode resultar em grandes quantidades de RAM sendo alocadas e não usadas quando as StringBuilder/Buffer
classes começam a crescer.
Em Java String x = "A" + "B";
usa um StringBuilder
nos bastidores. Portanto, para casos simples, não há benefício em declarar o seu. Mas se você estiver construindo String
objetos grandes, digamos menos que 4k, declarar StringBuilder sb = StringBuilder(4096);
é muito mais eficiente que concatenação ou usar o construtor padrão, que tem apenas 16 caracteres. Se o seu String
for menor que 10k, inicialize-o com o construtor para 10k para ser seguro. Mas, se for inicializado para 10k, você escrever 1 caractere a mais que 10k, será realocado e copiado para uma matriz de 20k. Portanto, inicializar alto é melhor do que baixo.
No caso de redimensionamento automático, no 17º caractere, a Matriz de backup é re-alocada e copiada para 32 caracteres; no 33º caractere, isso acontece novamente e você é re-alocado e copia a Matriz em 64 caracteres. Você pode ver como isso degenera em muitas re-alocações e cópias, o que você realmente está tentando evitar StringBuilder/Buffer
em primeiro lugar.
Isto é do código-fonte do JDK 6 para AbstractStringBuilder
void expandCapacity(int minimumCapacity) {
int newCapacity = (value.length + 1) * 2;
if (newCapacity < 0) {
newCapacity = Integer.MAX_VALUE;
} else if (minimumCapacity > newCapacity) {
newCapacity = minimumCapacity;
}
value = Arrays.copyOf(value, newCapacity);
}
Uma prática recomendada é inicializar StringBuilder/Buffer
um pouco maior do que você pensa que precisará, se não souber de imediato qual String
será o tamanho , mas você pode adivinhar. Uma alocação de um pouco mais de memória do que você precisa será melhor do que muitas re-alocações e cópias.
Lembre-se também de inicializar a StringBuilder/Buffer
com a, String
pois isso alocará apenas o tamanho dos caracteres String + 16, que na maioria dos casos apenas iniciarão o ciclo degenerado de re-alocação e cópia que você está tentando evitar. O seguinte é direto do código-fonte do Java 6.
public StringBuilder(String str) {
super(str.length() + 16);
append(str);
}
Se por acaso você acabar com uma instância StringBuilder/Buffer
que você não criou e não pode controlar o construtor chamado, existe uma maneira de evitar o comportamento degenerado de realocar e copiar. Ligue .ensureCapacity()
com o tamanho em que você deseja garantir que o resultado String
será adequado.
As alternativas:
Assim como uma nota, se você está fazendo realmente pesado String
construção e manipulação, há uma alternativa muito mais orientado para o desempenho chamada Cordas .
Outra alternativa é criar uma StringList
implementação subclassificando ArrayList<String>
e adicionando contadores para rastrear o número de caracteres em todas as .append()
operações de mutação da lista, substituindo-o .toString()
para criar StringBuilder
o tamanho exato de que você precisa, percorrendo a lista e construindo a saída, você pode até tornar StringBuilder
uma variável de instância e 'armazenar em cache' os resultados .toString()
e só precisa gerá-la novamente quando algo mudar.
Também não se esqueça de String.format()
criar saída formatada fixa, que pode ser otimizada pelo compilador à medida que a melhora.
String x = "A" + "B";
realmente compilar a ser um StringBuilder? Por que não basta compilar String x = "AB";
, ele deve usar um StringBuilder apenas se os componentes não forem conhecidos no momento da compilação.
Você quer dizer concatenação?
Exemplo do mundo real: você deseja criar uma nova string dentre muitas outras .
Por exemplo, para enviar uma mensagem:
Corda
String s = "Dear " + user.name + "<br>" +
" I saw your profile and got interested in you.<br>" +
" I'm " + user.age + "yrs. old too"
StringBuilder
String s = new StringBuilder().append.("Dear ").append( user.name ).append( "<br>" )
.append(" I saw your profile and got interested in you.<br>")
.append(" I'm " ).append( user.age ).append( "yrs. old too")
.toString()
Ou
String s = new StringBuilder(100).appe..... etc. ...
// The difference is a size of 100 will be allocated upfront as fuzzy lollipop points out.
StringBuffer (a sintaxe é exatamente como no StringBuilder, os efeitos diferem)
Sobre
StringBuffer
vs. StringBuilder
O primeiro é sincronizado e mais tarde não.
Portanto, se você invocá-lo várias vezes em um único encadeamento (que é 90% dos casos), StringBuilder
será executado muito mais rápido porque não parará para ver se possui o bloqueio do encadeamento.
Portanto, é recomendável usar StringBuilder
(a menos que você tenha mais de um encadeamento acessando ao mesmo tempo, o que é raro)
String
a concatenação ( usando o operador + ) pode ser otimizada pelo compilador para usar StringBuilder
embaixo, portanto, não é mais necessário se preocupar, nos dias anteriores do Java, isso era algo que todo mundo diz que deve ser evitado a todo custo, porque toda concatenação criou um novo objeto String. Compiladores modernos não fazem mais isso, mas ainda é uma boa prática usarStringBuilder
no caso de você usar um compilador "antigo".
editar
Apenas para quem está curioso, é isso que o compilador faz para esta classe:
class StringConcatenation {
int x;
String literal = "Value is" + x;
String builder = new StringBuilder().append("Value is").append(x).toString();
}
javap -c StringConcatenation
Compiled from "StringConcatenation.java"
class StringConcatenation extends java.lang.Object{
int x;
java.lang.String literal;
java.lang.String builder;
StringConcatenation();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: aload_0
5: new #2; //class java/lang/StringBuilder
8: dup
9: invokespecial #3; //Method java/lang/StringBuilder."<init>":()V
12: ldc #4; //String Value is
14: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
17: aload_0
18: getfield #6; //Field x:I
21: invokevirtual #7; //Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
24: invokevirtual #8; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
27: putfield #9; //Field literal:Ljava/lang/String;
30: aload_0
31: new #2; //class java/lang/StringBuilder
34: dup
35: invokespecial #3; //Method java/lang/StringBuilder."<init>":()V
38: ldc #4; //String Value is
40: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
43: aload_0
44: getfield #6; //Field x:I
47: invokevirtual #7; //Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
50: invokevirtual #8; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
53: putfield #10; //Field builder:Ljava/lang/String;
56: return
}
As linhas numeradas de 5 a 27 são para a String denominada "literal"
As linhas numeradas de 31 a 53 são para a String denominada "construtor"
Não há diferença, exatamente o mesmo código é executado para as duas strings.
StringBuilder
concatenação de String para executar no lado direito da tarefa. Qualquer boa implementação usará um StringBuilder nos bastidores, como você diz. Além disso, seu exemplo "a" + "b"
seria compilado em um único literal, "ab"
mas se você o usasse StringBuilder
, resultaria em duas chamadas desnecessárias para append()
.
"a"+"b"
mas dizer o que era uma concatenação de String, alterei para ser explícito. O que você não diz é: por que não é uma boa prática fazê-lo? É exatamente isso que um compilador (moderno) faz. @ distorcido, eu concordo, especialmente quando você sabe qual seria o tamanho da string final (aprox).
-------------------------------------------------- -------------------------------- String StringBuffer StringBuilder -------------------------------------------------- -------------------------------- Área de armazenamento | Pilha de Heap de Conjunto de Cordas Constantes Modificável Não (imutável) Sim (mutável) Sim (mutável) Segmento de Segmento | Sim Sim Não Desempenho | Rápido Muito lento Rápido -------------------------------------------------- --------------------------------
synchronised
e é por isso .
Corda
O String class
representa cadeias de caracteres. Todos os literais de cadeia de caracteres no programa Java, como "abc"
são implementados como instâncias desta classe.
Objetos de string são imutáveis, uma vez criados, não podemos mudar. ( Strings são constantes )
Se uma String for criada usando o construtor ou o método, essas strings serão armazenadas na Memória de Pilha e também SringConstantPool
. Porém, antes de salvar no pool, ele invoca o intern()
método para verificar a disponibilidade do objeto com o mesmo conteúdo no pool usando o método equals. Se a cópia de cadeia estiver disponível no pool, retornará a referência. Caso contrário, o objeto String será adicionado ao pool e retornará a referência.
+
) e à conversão de outros objetos em strings. A concatenação de strings é implementada por meio da classe StringBuilder (ou StringBuffer) e seu método de acréscimo.String heapSCP = new String("Yash");
heapSCP.concat(".");
heapSCP = heapSCP + "M";
heapSCP = heapSCP + 777;
// For Example: String Source Code
public String concat(String str) {
int otherLen = str.length();
if (otherLen == 0) {
return this;
}
int len = value.length;
char buf[] = Arrays.copyOf(value, len + otherLen);
str.getChars(buf, len);
return new String(buf, true);
}
Os literais de string são armazenados em StringConstantPool
.
String onlyPool = "Yash";
StringBuilder e StringBuffer são uma sequência mutável de caracteres. Isso significa que é possível alterar o valor desses objetos. StringBuffer possui os mesmos métodos que o StringBuilder, mas cada método no StringBuffer é sincronizado, portanto, é seguro para threads.
Os dados StringBuffer e StringBuilder podem ser criados apenas usando o novo operador. Portanto, eles são armazenados na memória Heap.
Instâncias do StringBuilder não são seguras para uso por vários threads. Se essa sincronização for necessária, é recomendável que StringBuffer seja usado.
StringBuffer threadSafe = new StringBuffer("Yash");
threadSafe.append(".M");
threadSafe.toString();
StringBuilder nonSync = new StringBuilder("Yash");
nonSync.append(".M");
nonSync.toString();
StringBuffer e StringBuilder está tendo um métodos especiais como.,
replace(int start, int end, String str)
E reverse()
.
NOTA : StringBuffer e SringBuilder são mutáveis, pois fornecem a implementação de
Appendable Interface
.
Quando usar qual.
Se você não vai mudar o valor toda vez, é melhor usar String Class
. Como parte de Genéricos, se você deseja Classificar Comparable<T>
ou comparar um valor, vá em String Class
.
//ClassCastException: java.lang.StringBuffer cannot be cast to java.lang.Comparable
Set<StringBuffer> set = new TreeSet<StringBuffer>();
set.add( threadSafe );
System.out.println("Set : "+ set);
Se você for modificar o valor toda vez que for para StringBuilder, que é mais rápido que StringBuffer. Se vários threads estiverem modificando o valor, vá para StringBuffer.
Além disso, StringBuffer
é seguro para threads, o que StringBuilder
não é.
Portanto, em uma situação em tempo real, quando diferentes threads estão acessando, StringBuilder
pode ter um resultado indeterminado.
Observe que se você estiver usando o Java 5 ou mais recente, deverá usar em StringBuilder
vez de StringBuffer
. Na documentação da API:
A partir do release JDK 5, essa classe foi complementada por uma classe equivalente projetada para uso por um único encadeamento
StringBuilder
,. AStringBuilder
classe geralmente deve ser usada preferencialmente a esta, pois suporta todas as mesmas operações, mas é mais rápida, pois não realiza sincronização.
Na prática, você quase nunca usará isso de vários threads ao mesmo tempo, portanto, a sincronização que StringBuffer
faz é quase sempre sobrecarga desnecessária.
Pessoalmente, não acho que exista nenhum uso no mundo real StringBuffer
. Quando é que eu gostaria de me comunicar entre vários threads manipulando uma sequência de caracteres? Isso não parece útil, mas talvez eu ainda não tenha visto a luz :)
A diferença entre String e as outras duas classes é que String é imutável e as outras duas são classes mutáveis.
Mas por que temos duas classes para o mesmo propósito?
A razão é que o StringBuffer
Thread é seguro e StringBuilder
não é.
StringBuilder
é uma nova classe ativada StringBuffer Api
e foi introduzida JDK5
e sempre é recomendada se você estiver trabalhando em um ambiente de encadeamento único, pois é muitoFaster
Para obter detalhes completos, você pode ler http://www.codingeek.com/java/stringbuilder-and-stringbuffer-a-way-to-create-mutable-strings-in-java/
Em java, String é imutável. Sendo imutável, queremos dizer que, uma vez que uma String é criada, não podemos alterar seu valor. StringBuffer é mutável. Depois que um objeto StringBuffer é criado, apenas anexamos o conteúdo ao valor do objeto em vez de criar um novo objeto. StringBuilder é semelhante ao StringBuffer, mas não é seguro para threads. Os métodos do StingBuilder não são sincronizados, mas em comparação com outras Strings, o Stringbuilder roda mais rápido. Você pode aprender a diferença entre String, StringBuilder e StringBuffer implementando-os.