StringBuffer et StringBuilder en Java
Prérequis
Maîtriser la classe String et son immuabilité. Comprendre les notions d'objet et de méthode en Java. Avoir des bases sur la notion de thread et de synchronisation (pour distinguer StringBuffer de StringBuilder).
Objectifs
Comprendre pourquoi et quand utiliser StringBuffer et StringBuilder à la place de String. Maîtriser les méthodes essentielles de modification de chaînes : append, insert, replace, delete, reverse. Savoir choisir entre les trois classes selon le contexte.
1. Rappel — La limite de String
String crée un nouvel objet en mémoire. Dans une boucle qui concatène des milliers de chaînes, cela génère autant d'objets temporaires et peut sérieusement dégrader les performances.
String resultat = "";
for (int i = 0; i < 10000; i++) {
resultat += i;
}
Ce code crée 10 000 objets String intermédiaires. Avec StringBuilder, un seul objet est modifié en place.StringBuffer et StringBuilder sont des classes Java qui représentent des séquences de caractères modifiables. Contrairement à String, leur contenu peut être modifié sans créer de nouveaux objets.2. StringBuffer vs StringBuilder vs String
| Critère | String |
StringBuffer |
StringBuilder |
|---|---|---|---|
| Modifiable | Non (immuable) | Oui | Oui |
| Thread-safe | Oui (immuable) | Oui (synchronisé) | Non |
| Performance | Faible si beaucoup de concaténations | Moyenne (synchronisation coûteuse) | Haute (pas de synchronisation) |
| Usage recommandé | Chaînes fixes, peu de modifications | Multithread avec modifications | Mono-thread avec nombreuses modifications |
| Package | java.lang |
java.lang |
java.lang |
StringBuilder — il est plus rapide que StringBuffer. Réservez StringBuffer aux contextes multithread où plusieurs threads accèdent et modifient la même instance.3. La classe StringBuffer
StringBuffer est une classe Java représentant une séquence de caractères modifiable et thread-safe. Ses méthodes sont synchronisées, ce qui garantit un accès sécurisé depuis plusieurs threads simultanément.3.1 Constructeurs
| Constructeur | Description |
|---|---|
StringBuffer() |
Crée un tampon vide avec une capacité initiale de 16 caractères |
StringBuffer(String str) |
Crée un tampon initialisé avec la chaîne str |
StringBuffer(int capacity) |
Crée un tampon vide avec la capacité spécifiée |
Complément — Capacité vs Longueur
La longueur (length()) est le nombre de caractères actuellement stockés. La capacité (capacity()) est la taille du tampon interne alloué. La capacité initiale d'un StringBuffer(String s) est s.length() + 16. Quand la capacité est dépassée, Java la double automatiquement.
3.2 Méthodes principales
| Méthode | Description |
|---|---|
append(String s) |
Ajoute s à la fin. Surchargée pour tous les types (int, char, double…) |
insert(int offset, String s) |
Insère s à la position offset |
replace(int start, int end, String str) |
Remplace les caractères de start à end (exclu) par str |
delete(int start, int end) |
Supprime les caractères de start à end (exclu) |
deleteCharAt(int index) |
Supprime le caractère à l'indice index |
reverse() |
Inverse l'ordre des caractères |
charAt(int index) |
Retourne le caractère à la position index |
length() |
Retourne le nombre de caractères courant |
capacity() |
Retourne la capacité du tampon interne |
substring(int begin) |
Retourne la sous-chaîne à partir de begin |
substring(int begin, int end) |
Retourne la sous-chaîne de begin à end (exclu) |
toString() |
Convertit le StringBuffer en String |
Exemple 1 — Opérations sur StringBuffer
public class TestStringBuffer {
public static void main(String[] args) {
StringBuffer s = new StringBuffer("Developpement Informatique");
System.out.println("Longueur : " + s.length());
System.out.println("Capacité : " + s.capacity());
s.append(".com");
System.out.println("Après append : " + s);
s.insert(13, "-");
System.out.println("Après insert : " + s);
s.reverse();
System.out.println("Après reverse : " + s);
s.delete(0, 5);
System.out.println("Après delete(0,5): " + s);
s.deleteCharAt(7);
System.out.println("Après deleteCharAt(7): " + s);
s.replace(0, 5, "Meknes");
System.out.println("Après replace : " + s);
}
}
Longueur : 26 Capacité : 42 Après append : Developpement Informatique.com Après insert : Developpement- Informatique.com Après reverse : moc.euqitamrofnI -tnemeppoleveD Après delete(0,5): uqitamrofnI -tnemeppoleveD Après deleteCharAt(7): uqitamrfnI -tnemeppoleveD Après replace : MeknesmrfnI -tnemeppoleveD
3.3 Chaînage de méthodes
Chaque méthode modificatrice de StringBuffer retourne l'objet lui-même. Cela permet de chaîner les appels sur une même ligne, rendant le code plus concis.
StringBuffer sb = new StringBuffer();
sb.append("Bonjour")
.append(", ")
.append("Java")
.append(" !")
.insert(8, "beau ");
System.out.println(sb);
Bonjour, beau Java !
3.4 Faits importants sur StringBuffer
StringBufferhérite de la classeObject.- Elle implémente les interfaces
Serializable,AppendableetCharSequence. - Ses méthodes sont synchronisées — sûres pour les environnements multithread.
- Elle hérite de
Objectles méthodesequals,hashCode,toString,getClass.
4. La classe StringBuilder
StringBuilder est fonctionnellement identique à StringBuffer mais ses méthodes ne sont pas synchronisées. Elle est donc plus rapide en contexte mono-thread, ce qui couvre la quasi-totalité des cas d'usage courants.
StringBuilder sb = new StringBuilder();
StringBuilder sb = new StringBuilder("texte initial");
StringBuilder sb = new StringBuilder(256);
Exemple 2 — StringBuilder pour concaténation performante
public class TestStringBuilder {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
for (int i = 1; i <= 5; i++) {
sb.append("item").append(i);
if (i < 5) sb.append(", ");
}
System.out.println(sb);
sb.insert(0, "[").append("]");
System.out.println(sb);
sb.delete(7, 13);
System.out.println(sb);
System.out.println("Longueur : " + sb.length());
String resultat = sb.toString();
System.out.println("Converti en String : " + resultat);
}
}
item1, item2, item3, item4, item5 [item1, item2, item3, item4, item5] [item1, item3, item4, item5] Longueur : 28 Converti en String : [item1, item3, item4, item5]
4.1 StringBuilder et les boucles — comparaison de performance
Application — Mesure du temps de concaténation
int N = 50_000;
long debut = System.currentTimeMillis();
String s = "";
for (int i = 0; i < N; i++) {
s += i;
}
long fin = System.currentTimeMillis();
System.out.println("String : " + (fin - debut) + " ms");
debut = System.currentTimeMillis();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < N; i++) {
sb.append(i);
}
fin = System.currentTimeMillis();
System.out.println("StringBuilder : " + (fin - debut) + " ms");
String : ~1200 ms StringBuilder : ~2 ms
+ en utilisant StringBuilder en coulisse. Cependant, cette optimisation ne s'applique pas aux concaténations à l'intérieur des boucles. C'est là que l'utilisation explicite de StringBuilder est indispensable.5. Méthodes communes — Tableau récapitulatif
| Méthode | Description | Exemple |
|---|---|---|
append(x) |
Ajoute x à la fin |
sb.append("!") |
insert(i, x) |
Insère x à l'indice i |
sb.insert(0, "Début: ") |
replace(a, b, s) |
Remplace les caractères [a, b[ par s |
sb.replace(2, 5, "XYZ") |
delete(a, b) |
Supprime les caractères [a, b[ | sb.delete(0, 3) |
deleteCharAt(i) |
Supprime le caractère à l'indice i |
sb.deleteCharAt(5) |
reverse() |
Inverse la séquence | sb.reverse() |
charAt(i) |
Retourne le caractère à l'indice i |
sb.charAt(0) |
length() |
Longueur actuelle | sb.length() |
capacity() |
Capacité du tampon | sb.capacity() |
substring(a) |
Sous-chaîne de a à la fin |
sb.substring(3) |
substring(a, b) |
Sous-chaîne de a à b (exclu) |
sb.substring(2, 6) |
indexOf(s) |
Première occurrence de s |
sb.indexOf("Java") |
toString() |
Conversion en String immuable |
sb.toString() |
6. Exercice
Construire et manipuler une chaîne avec StringBuilder
Écrire un programme Java qui utilise StringBuilder pour construire et manipuler une phrase étape par étape.
Travail demandé
- Créer un
StringBuildervide. - Ajouter les mots
"Java"," est"," un"et" langage"avecappend(). - Insérer
" beau"avant" langage"avecinsert(). - Remplacer
"Java"par"Python"avecreplace()(utiliserindexOf()pour trouver la position). - Ajouter un point d'exclamation à la fin.
- Afficher la longueur, la capacité et la chaîne finale.
- Vérifier si la chaîne finale contient
"beau"après conversion enString.
Après appends : Java est un langage Après insert : Java est un beau langage Après replace : Python est un beau langage Après append ! : Python est un beau langage ! Longueur : 27 Capacité : 34 Contient "beau" : true
public class ExerciceStringBuilder {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
sb.append("Java")
.append(" est")
.append(" un")
.append(" langage");
System.out.println("Après appends : " + sb);
int posLangage = sb.indexOf(" langage");
sb.insert(posLangage, " beau");
System.out.println("Après insert : " + sb);
int posJava = sb.indexOf("Java");
sb.replace(posJava, posJava + 4, "Python");
System.out.println("Après replace : " + sb);
sb.append(" !");
System.out.println("Après append ! : " + sb);
System.out.println("Longueur : " + sb.length());
System.out.println("Capacité : " + sb.capacity());
String resultat = sb.toString();
System.out.println("Contient \"beau\" : " + resultat.contains("beau"));
}
}
Après appends : Java est un langage Après insert : Java est un beau langage Après replace : Python est un beau langage Après append ! : Python est un beau langage ! Longueur : 27 Capacité : 34 Contient "beau" : true
- Chaînage : les méthodes
append()retournent l'objetStringBuilderlui-même, permettant de chaîner les appels sur plusieurs lignes. indexOf(): utilisé pour trouver la position dynamiquement, sans coder une position en dur qui deviendrait fausse après chaque modification.replace(posJava, posJava + 4, "Python"):posJava + 4car"Java"contient 4 caractères — l'intervalle est [posJava, posJava+4[.toString(): nécessaire pour utiliser les méthodes deStringcommecontains()—StringBuilderne les possède pas toutes.- Capacité = 34 : la capacité initiale d'un
StringBuilder()vide est 16. Après le premierappend("Java")qui dépasse 16, Java double la capacité et ajoute 2 :(16+1) × 2 = 34.
L'essentiel en bref
Là où String est immuable et crée un nouvel objet à chaque modification, StringBuilder et StringBuffer maintiennent un tampon mutable — idéal pour les nombreuses concaténations ou transformations. Les deux partagent la même API : append() pour ajouter, insert() pour insérer, replace() et delete() pour modifier, reverse() pour inverser. La différence clé est la synchronisation : StringBuffer est thread-safe (méthodes synchronisées) au prix de performances moindres, tandis que StringBuilder est plus rapide mais réservé aux contextes mono-thread. En pratique, utilisez toujours StringBuilder sauf si votre code est explicitement multithread. Terminez toujours avec toString() pour récupérer un String immuable standard.