web-dev-qa-db-fra.com

Quelle est la différence entre String et StringBuffer en Java?

Quelle est la différence entre String et StringBuffer en Java?

Existe-t-il une taille maximale pour String?

63
Praveen

String est utilisé pour manipuler des chaînes de caractères qui ne peuvent pas être changées (en lecture seule et immuables). 

StringBuffer est utilisé pour représenter les caractères pouvant être modifiés.

En ce qui concerne les performances, StringBuffer est plus rapide lors des concaténations. En effet, lorsque vous concaténez une String, vous créez un nouvel objet (en interne) chaque fois que String est immuable.

Vous pouvez également utiliser StringBuilder qui est similaire à StringBuffer sauf que ce n'est pas synchronisé. La taille maximale de l’un ou l’autre de ces éléments est Integer.MAX_VALUE (231 - 1 = 2 147 483 647) ou taille de segment maximale divisée par 2 (voir Combien de caractères une chaîne Java peut-elle avoir? ) . Plus d'informations ici .

75
Vivin Paliath

Un String est immuable, c’est-à-dire que lorsqu’il est créé, il ne peut jamais changer.

Une StringBuffer (ou son cousin non synchronisé StringBuilder) est utilisée lorsque vous devez construire une chaîne pièce par pièce sans la surcharge de performances liée à la construction de nombreux Strings en cours de route.

La longueur maximale pour les deux est Integer.MAX_VALUE, car ils sont stockés en interne sous forme de tableaux, et les tableaux Java ont uniquement une valeur int pour leur pseudo-champ de longueur.

L’amélioration des performances entre Strings et StringBuffers pour la concaténation multiple est assez significative. Si vous exécutez le code de test suivant, vous verrez la différence. Sur mon ancien ordinateur portable avec Java 6, j'obtiens les résultats suivants:

 Concat avec String pris: 1781ms 
 Concat avec StringBuffer pris: 0ms 
public class Concat
{
    public static String concatWithString()
    {
        String t = "Cat";
        for (int i=0; i<10000; i++)
        {
            t = t + "Dog";
        }
        return t;
    }
    public static String concatWithStringBuffer()
    {
        StringBuffer sb = new StringBuffer("Cat");
        for (int i=0; i<10000; i++)
        {
            sb.append("Dog");
        }
        return sb.toString();
    }
    public static void main(String[] args)
    {
        long start = System.currentTimeMillis();
        concatWithString();
        System.out.println("Concat with String took: " + (System.currentTimeMillis() - start) + "ms");
        start = System.currentTimeMillis();
        concatWithStringBuffer();
        System.out.println("Concat with StringBuffer took: " + (System.currentTimeMillis() - start) + "ms");
    }
}
34
Simon Nickerson
String                                          StringBuffer

Immutable                                       Mutable
String s=new String("karthik");                StringBuffer sb=new StringBuffer("karthik")
s.concat("reddy");                             sb.append("reddy");
System.out.println(s);                         System.out.println(sb);
O/P:karthik                                    O/P:karthikreddy

--->once we created a String object            ---->once we created a StringBuffer object
we can't perform any changes in the existing  we can perform any changes in the existing
object.If we are trying to perform any        object.It is nothing but mutablity of 
changes with those changes a new object       of a StrongBuffer object
will be created.It is nothing but Immutability
of a String object

Use String--->If you require immutabilty
Use StringBuffer---->If you require mutable + threadsafety
Use StringBuilder--->If you require mutable + with out threadsafety

String s=new String("karthik");
--->here 2 objects will be created one is heap and the other is in stringconstantpool(scp) and s is always pointing to heap object

String s="karthik"; 
--->In this case only one object will be created in scp and s is always pointing to that object only
23
Karthik Reddy

String est une classe immuable. Cela signifie qu'une fois que vous instanciez une instance d'une chaîne comme ceci:

String str1 = "hello";

L'objet en mémoire ne peut pas être modifié. Au lieu de cela, vous devrez créer une nouvelle instance, copier l'ancienne chaîne et ajouter le reste, comme dans cet exemple:

String str1 = "hello";
str1 = str1 + " world!";

Ce qui se passe réellement, c’est d’entendre dire que nous ne mettons PAS à jour l’objet str1 existant ... nous réallouons une nouvelle mémoire en même temps, copions les données "hello" et ajoutons le "monde"! à la fin, configurez ensuite la référence str1 pour qu'elle pointe vers cette nouvelle mémoire. Donc, ça ressemble vraiment plus à ça sous le capot:

String str1 = "hello";
String str2 = str1 + " world!";
str1 = str2;

Il en résulte que ce processus "copier/coller et déplacer des éléments en mémoire" peut être très coûteux s'il est effectué de manière répétitive, en particulier de manière récursive.

Lorsque vous êtes dans cette situation de devoir faire des choses encore et encore, utilisez StringBuilder. Il est modifiable et peut ajouter des chaînes à la fin de la chaîne actuelle car il est renvoyé par un [tableau en croissance] (et non 100% s'il s'agit de la structure de données réelle, il pourrait s'agir d'une liste).

10
Feisty Mango

De la API:

Une séquence de caractères mutable et sécurisée pour les threads. Un tampon de chaîne est comme une chaîne, mais peut être modifié. À tout moment, il contient une séquence de caractères particulière, mais sa longueur et son contenu peuvent être modifiés via certains appels de méthode. 

4
posdef

J'ai trouvé intérêt réponse pour comparer les performances String vs StringBuffer par Reggie Hutcherso Source: http://www.javaworld.com/javaworld/jw-03-2000/jw-0324-javaperf.html

Java fournit les classes StringBuffer et String, et la classe String est utilisée pour manipuler des chaînes de caractères qui ne peuvent pas être modifiées. En termes simples, les objets de type String sont en lecture seule et immuables. La classe StringBuffer est utilisée pour représenter les caractères pouvant être modifiés.

La différence de performances significative entre ces deux classes est que StringBuffer est plus rapide que String lors de la réalisation de concaténations simples. Dans le code de manipulation de chaîne, les chaînes de caractères sont systématiquement concaténées. À l'aide de la classe String, les concaténations sont généralement effectuées comme suit:

 String str = new String ("Stanford  ");
 str += "Lost!!";

Si vous utilisiez StringBuffer pour effectuer la même concaténation, vous auriez besoin d'un code ressemblant à ceci:

 StringBuffer str = new StringBuffer ("Stanford ");
 str.append("Lost!!");

Les développeurs supposent généralement que le premier exemple ci-dessus est plus efficace car ils pensent que le second exemple, qui utilise la méthode append pour la concaténation, est plus coûteux que le premier exemple, qui utilise l'opérateur + pour concaténer deux objets String.

L'opérateur + semble innocent, mais le code généré produit des surprises. L'utilisation d'un StringBuffer pour la concaténation peut en effet produire un code beaucoup plus rapide que l'utilisation d'un String. Pour découvrir pourquoi c'est le cas, nous devons examiner le bytecode généré à partir de nos deux exemples. Le bytecode pour l'exemple utilisant String ressemble à ceci:

0 new #7 <Class Java.lang.String>
3 dup 
4 ldc #2 <String "Stanford ">
6 invokespecial #12 <Method Java.lang.String(Java.lang.String)>
9 astore_1
10 new #8 <Class Java.lang.StringBuffer>
13 dup
14 aload_1
15 invokestatic #23 <Method Java.lang.String valueOf(Java.lang.Object)>
18 invokespecial #13 <Method Java.lang.StringBuffer(Java.lang.String)>
21 ldc #1 <String "Lost!!">
23 invokevirtual #15 <Method Java.lang.StringBuffer append(Java.lang.String)>
26 invokevirtual #22 <Method Java.lang.String toString()>
29 astore_1

Le bytecode aux emplacements 0 à 9 est exécuté pour la première ligne de code, à savoir:

 String str = new String("Stanford ");

Ensuite, le bytecode aux emplacements 10 à 29 est exécuté pour la concaténation:

 str += "Lost!!";

Les choses deviennent intéressantes ici. Le bytecode généré pour la concaténation crée un objet StringBuffer, puis invoque sa méthode append: l'objet StringBuffer temporaire est créé à l'emplacement 10 et sa méthode append est appelée à l'emplacement 23. La classe String étant immuable, un StringBuffer doit être utilisé pour enchaînement.

Une fois la concaténation effectuée sur l'objet StringBuffer, il doit être reconverti en chaîne. Cette opération est effectuée avec l'appel de la méthode toString à l'emplacement 26. Cette méthode crée un nouvel objet String à partir de l'objet StringBuffer temporaire. La création de cet objet StringBuffer temporaire et sa conversion ultérieure en objet String sont très coûteuses.

En résumé, les deux lignes de code ci-dessus entraînent la création de trois objets:

  1. Un objet String à l'emplacement 0
  2. Un objet StringBuffer à l'emplacement 10
  3. Un objet String à l'emplacement 26

Maintenant, regardons le bytecode généré pour l'exemple en utilisant StringBuffer:

0 new #8 <Class Java.lang.StringBuffer>
3 dup
4 ldc #2 <String "Stanford ">
6 invokespecial #13 <Method Java.lang.StringBuffer(Java.lang.String)>
9 astore_1
10 aload_1 
11 ldc #1 <String "Lost!!">
13 invokevirtual #15 <Method Java.lang.StringBuffer append(Java.lang.String)>
16 pop

Le bytecode aux emplacements 0 à 9 est exécuté pour la première ligne de code:

 StringBuffer str = new StringBuffer("Stanford ");

Le bytecode aux emplacements 10 à 16 est ensuite exécuté pour la concaténation:

 str.append("Lost!!");

Notez que, comme dans le premier exemple, ce code appelle la méthode append d'un objet StringBuffer. Contrairement au premier exemple, toutefois, il n'est pas nécessaire de créer un StringBuffer temporaire, puis de le convertir en objet String. Ce code crée un seul objet, StringBuffer, à l'emplacement 0.

En conclusion, la concaténation StringBuffer est nettement plus rapide que la concaténation String. De toute évidence, StringBuffers devrait être utilisé dans ce type d'opération lorsque cela est possible. Si vous souhaitez utiliser les fonctionnalités de la classe String, envisagez d'utiliser un StringBuffer pour la concaténation, puis effectuez une conversion en String.

2
NguyenDat

Un StringBuffer est utilisé pour créer une seule chaîne à partir de plusieurs chaînes, par exemple. lorsque vous souhaitez ajouter des parties d'une chaîne dans une boucle.

Vous devez utiliser un StringBuilder au lieu d'un StringBuffer lorsque vous n'avez qu'un seul Thread accédant au StringBuffer, car StringBuilder n'est pas synchronisé et donc plus rapide.

Autant que je sache, Java n’a pas de limite supérieure pour la taille de chaîne, mais les machines virtuelles ont probablement une limite supérieure.

2
Thomas Lötzer

En imprimant le hashcode de l'objet String/StringBuffer après chaque opération d'ajout, cela prouve également que l'objet String est recréé en interne à chaque fois avec de nouvelles valeurs plutôt que d'utiliser le même objet String.

public class MutableImmutable {

/**
 * @param args
 */
public static void main(String[] args) {
    System.out.println("String is immutable");
    String s = "test";
    System.out.println(s+"::"+s.hashCode());
    for (int i = 0; i < 10; i++) {
        s += "tre";
        System.out.println(s+"::"+s.hashCode());
    }

    System.out.println("String Buffer is mutable");

    StringBuffer strBuf = new StringBuffer("test");
    System.out.println(strBuf+"::"+strBuf.hashCode());
    for (int i = 0; i < 10; i++) {
        strBuf.append("tre");
        System.out.println(strBuf+"::"+strBuf.hashCode());
    }

 }

}

Sortie: Il imprime la valeur de l'objet avec son hashcode

    String is immutable
    test::3556498
    testtre::-1422435371
    testtretre::-1624680014
    testtretretre::-855723339
    testtretretretre::2071992018
    testtretretretretre::-555654763
    testtretretretretretre::-706970638
    testtretretretretretretre::1157458037
    testtretretretretretretretre::1835043090
    testtretretretretretretretretre::1425065813
    testtretretretretretretretretretre::-1615970766
    String Buffer is mutable
    test::28117098
    testtre::28117098
    testtretre::28117098
    testtretretre::28117098
    testtretretretre::28117098
    testtretretretretre::28117098
    testtretretretretretre::28117098
    testtretretretretretretre::28117098
    testtretretretretretretretre::28117098
    testtretretretretretretretretre::28117098
    testtretretretretretretretretretre::28117098
2
DeepaGanesh

Bien que je comprenne que ce n’est pas un facteur de différenciation majeur, j’ai remarqué aujourd’hui que StringBuffer (et StringBuilder) fournit des méthodes intéressantes, contrairement à String.

  • sens inverse()
  • setCharAt ()
1
jaydeep

Un String est un tableau de caractères immuable.

StringBuffer est un tableau de caractères mutable. Souvent reconverti en String lorsque la mutation est terminée.

Puisque les deux sont un tableau, la taille maximale des deux est égale à la taille maximale d'un entier, qui est 2 ^ 31-1 (voir JavaDoc , consultez également le JavaDoc pour String et StringBuffer parce que l'argument .length d'un tableau est une primitive int. (Voir Tableaux ).

1
Pindatjuh

Un StringBuffer ou son frère plus jeune et plus rapide StringBuilder est préféré lorsque vous allez faire beaucoup de concaténations de chaînes à la saveur de

string += newString;

ou équivalent

string = string + newString;

parce que les constructions ci-dessus créent implicitement la chaîne new à chaque fois, ce qui sera une performance énorme. StringBuffer/StringBuilder est mieux à l’écart pour être comparé à un List<Character> dynamiquement extensible.

1
BalusC

Les différences sont

  1. Seulement dans String class + l'opérateur est surchargé. Nous pouvons concaténer deux objets String en utilisant + opérateur, mais dans le cas de StringBuffer nous ne le pouvons pas.
  2. String class remplace toString (), equals (), hashCode () de Object class, mais StringBuffer ne remplace que toString ().

    String s1 = new String("abc");
    String s2 = new String("abc");
    System.out.println(s1.equals(s2));  // output true
    
    StringBuffer sb1 = new StringBuffer("abc");
    StringBuffer sb2 = new StringBuffer("abc");
    System.out.println(sb1.equals(sb2));  // output false
    
  3. String class est à la fois Serializable ainsi que Comparable , mais StringBuffer est seulement Serializable .

    Set<StringBuffer> set = new TreeSet<StringBuffer>();
    set.add(sb1);
    set.add(sb2);
    System.out.println(set);  // gives ClassCastException because there is no Comparison mechanism
    
  4. Nous pouvons créer un objet String avec et sans l'opérateur new , mais l'objet StringBuffer ne peut être créé qu'avec l'opérateur new .

  5. String est immuable mais StringBuffer est modifiable.
  6. StringBuffer est synchronisé, alors que String ne l'est pas.
  7. StringBuffer a une méthode reverse () intégrée, mais String ne l’a pas.
1
Arun Sudhakaran

String est immuable, ce qui signifie que lorsque vous effectuez une opération sur une chaîne, vous créez réellement une nouvelle chaîne.

StringBuffer est modifiable et vous pouvez l'ajouter ou le réinitialiser à 0.

En pratique, le compilateur semble utiliser StringBuffer lors de la concaténation de chaînes pour des raisons de performances .

1
Matthew Willis
String is immutable. 

Pourquoi? Vérifiez ici .

StringBuffer is not. It is thread safe. 

D'autres questions, telles que savoir quand utiliser quels concepts et d'autres, peuvent être comprises à la suite de this .

J'espère que cela t'aides.

1
roger_that

En termes de performances, StringBuffer est bien meilleur que String; Parce que chaque fois que vous appliquez une concaténation sur un objet String, un nouvel objet String est créé à chaque concaténation.

Règle principale: String sont immuables (non modifiable) et StringBuffer est modifiable (modifiable) 

Voici l'expérience expérimentale où vous obtenez la différence de performance 

public class Test {

  public static int LOOP_ITERATION= 100000;

  public static void stringTest(){
    long startTime = System.currentTimeMillis();
    String string = "This";
    for(int i=0;i<LOOP_ITERATION;i++){
        string = string+"Yasir";
    }

    long endTime = System.currentTimeMillis();
    System.out.println(endTime - startTime);    
  }

  public static void stringBufferTest(){
    long startTime = System.currentTimeMillis();
    StringBuffer stringBuffer = new StringBuffer("This");
    for(int i=0;i<LOOP_ITERATION;i++){
        stringBuffer.append("Yasir");
    }

    long endTime = System.currentTimeMillis();
    System.out.println(endTime - startTime);
  }

  public static void main(String []args){
    stringTest()
    stringBufferTest(); 
  }
 }

Les sorties de String sont dans ma machine 14800

Les sorties de StringBuffer sont dans ma machine 14