No Java podemos representar sequências de caracteres para exibirmos mensagens, armazenarmos informações e fazermos outros usos diversos. E a forma mais popular de se trabalhar com cadeia de caracteres é através das Strings, que são rápidas e eficientes nisso.
A classe String representa uma cadeia de caracteres. Todas as strings literais em um programa Java, assim como "abc", são implementadas como instância de uma classe String. E se tratando de uma classe, a mesma não é um tipo de dado primitivo e sim um TAD (tipo abstrato de dado).
Outras classes que podemos trabalhar também com cadeia de caracteres são as classes StringBuffer e StringBuilder. Mas, qual devemos usar? O objetivo desse artigo é esclarecer esse ponto.
![]() |
String x StringBuffer x StringBuilder - qual usar? |
Entendendo as Strings
A String pertence ao pacote java.lang, assim como StringBuffer e StringBuilder, logo não precisa ser importada em seus programas. Eis algumas maneiras de se criar uma String:
public class Exemplo1 {
public static void main(String[] args) {
//Atribuição direta
String a = "Mensagem 1";
//Separação entre a instanciação e atribuição
String b = new String();
b = "Mensagem 2";
//Passando um vetor de caracteres de char como argumento
char msg[] = {'M', 'e', 'n', 's', 'a', 'g', 'e', 'm', ' ', '3'};
String c = new String(msg);
//Passando uma sequência de caracteres diretamente como argumento
String d = new String("Mensagem 4");
System.out.println(a);
System.out.println(b);
System.out.println(c);
System.out.println(d);
}
}
A saída será:
Mensagem 1
Mensagem 2
Mensagem 3
Mensagem 4
Até aqui não há nenhum problema em fazer o uso delas. Mas e se quisermos alterar a mensagem de uma String através da concatenação com o operador "+"? Veja:
public class Exemplo2 {
public static void main(String[] args) {
String msg = "a";
msg = msg + "bc";
System.out.println(msg);
}
}
A saída será:abc
O que aconteceu nesse exemplo foi a instanciação de uma nova String com a sequência de caracteres "a" e "bc", na qual msg faz referência (após deixar de referenciar "a"). Mas "a" ainda está na memória do computador, só que em um outro local. Dentro da String há o seguinte atributo, onde a sequência de caracteres é armazenada:
private final char value[];
Como podemos perceber, não há mesmo como modificar o valor da String já que ele é final, ou seja, é impossível redimensionar o vetor para acomodar mais algum caractere (por isso Strings são tidas como imutáveis). A forma mais apropriada de se realizar essa tarefa seria copiando a String original e concatenando com a String que foi passada, gerando uma nova String mas esse processo pode levar muito tempo e acumular muitos objetos na memória.
Concatenar muitas Strings é uma Má Ideia
Considere o exemplo a seguir e a sua respectiva saída em um Intel Celeron N2808 @ 2x 2.2491GHz com 4 GB de memória RAM:
public class Exemplo3 {
public static void main(String[] args) {
String msg = "";
double x, x0, deltaX;
x0 = System.nanoTime(); //tempo inicial (nanossegundos)
for (int i = 0; i < 36_600; i++) {
msg = msg + i;
}
x = System.nanoTime(); //tempo final (nanossegundos)
deltaX = (x - x0)/Math.pow(10, 9); //conversão para segundos
System.out.printf("Segundos passados: %.0f\n", deltaX);
}
}
Saída:Segundos passados: 11
Em sua máquina o resultado pode ser diferente, mas a observação a se fazer é que para 36.600 concatenações foi preciso um tempo considerável, além do uso da memória para guardar cada novo objeto resultante da concatenação.
StringBuilder e StringBuffer
Tanto StringBuilder quanto StringBuffer suportam mutações de caracteres. Vejamos o mesmo código demonstrado anteriormente, só que agora utilizando StringBuffer.
public class Exemplo4 {
public static void main(String[] args) {
StringBuffer msg = new StringBuffer();
double x, x0, deltaX;
x0 = System.nanoTime();
for (int i = 0; i < 36_600; i++) {
msg.append(i); //método para concatenação
}
x = System.nanoTime();
deltaX = (x - x0)/Math.pow(10, 9);
System.out.printf("Segundos passados: %.5f\n", deltaX);
}
}
Saída:
Segundos passados: 0,01787
O resultado foi 61.556% (sessenta e um mil quinhentos e cinquenta e seis por cento) menor. Com StringBuilder o resultado é de 0,03031 segundos, que também é um valor relativamente muito baixo.
StringBuffer:
Uma thread-safe — isto é, que manipula EDs (estrutura de dados) compartilhadas entre diversas threads de forma segura —, sequência de caracteres mutáveis. Uma StringBuffer é como uma String, mas pode ser modificada, pois o tamanho e conteúdo da sequência podem ser alterados através da chamada de certos métodos.
Explicando de uma maneira simplificada: ela recebe a String, que é passada para o método append, e ele chama o método append da sua super classe (que é abstrata). A lógica é aumentar a capacidade do vetor de caracteres, manter a sequência de caracteres anterior e adicionar esse novo conteúdo a ele (o vetor de char).
StringBuilder:
Uma sequência de caracteres mutáveis. Essa classe fornece uma API compatível com StringBuffer, mas com a não-garantia de sincronização (o que a diferencia da StringBuffer). Essa classe é designada para uso como uma substituta para StringBuffer onde ela será usada por uma única thread (como geralmente acontece).
Sempre que possível essa classe é recomendada, já que é mais rápida que a StringBuffer na maioria das implementações. Tanto a StringBuffer quanto a StringBuilder, se instanciadas sem nenhum conteúdo, iniciam com a capacidade total de 16 caracteres.
Conclusão
A String deve ser usada sempre que sua aplicação exigir poucas concatenações, já que Strings são imutáveis e portanto sempre criarão um novo objeto na memória com o novo conteúdo acrescentado.
StringBuffer e StringBuilder devem ser utilizadas sempre que houver um número elevado de concatenações em sua aplicação, e se precisar converter para String para exibir uma mensagem ou armazenar em algum lugar, basta usar o método toString(). A diferença entre StringBuffer e StringBuilder é a questão da sincronização, portanto a primeira é mais recomendada para se trabalhar com threads.
Referências
JAVA PLATFORM SE 7. StringBuilder. Disponível em <https://docs.oracle.com/javase/7/docs/api/java/lang/StringBuilder.html>. Acesso em 19 abr. 2017.
JAVA PLATFORM SE 7. StringBuffer. Disponível em <https://docs.oracle.com/javase/7/docs/api/java/lang/StringBuffer.html>. Acesso em 19 abr. 2017.
JAVA PLATFORM SE 7. String. Disponível em <https://docs.oracle.com/javase/7/docs/api/java/lang/String.html>. Acesso em 19 abr. 2017.
Para citar esse artigo:
Comentários
Postar um comentário