StringBuilder et StringBuffer

11-Java SE StringBuilder et StringBuffer

Au cours de ce tutoriel, nous explorerons en détail les fonctionnalités de StringBuilder et StringBuffer en Java , en apprendrons sur leurs différences subtiles, et découvrirons comment les utiliser de manière efficace dans nos projets Java. Nous discuterons également des bonnes pratiques pour optimiser l’utilisation de ces classes et améliorer les performances de nos applications.

accès rapide

La démo

Introduction

Dans le vaste univers de la programmation Java, la manipulation de chaînes de caractères est une tâche courante et incontournable. Que ce soit pour la construction de messages utilisateur, la génération de rapports ou le traitement de données, les chaînes de caractères sont omniprésentes dans pratiquement tous les programmes Java. Cependant, la manipulation de ces chaînes peut parfois entraîner des problèmes de performance et d’efficacité.

Création d’un objet StringBuilder ou StringBuffer

Vous pouvez créer des objets StringBuilder et StringBuffer de plusieurs manières similaires :

// Création d'un objet StringBuilder vide
StringBuilder stringBuilder = new StringBuilder();

// Création d'un objet StringBuilder avec une valeur initiale
StringBuilder stringBuilderWithValue = new StringBuilder("Initial Value");

// Création d'un objet StringBuffer vide
StringBuffer stringBuffer = new StringBuffer();

// Création d'un objet StringBuffer avec une valeur initiale
StringBuffer stringBufferWithValue = new StringBuffer("Initial Value");

Pourquoi utiliser StringBuilder ou StringBuffer-?

  1. Mutabilité : Les objets StringBuilder et StringBuffer sont mutables, ce qui signifie qu’ils peuvent être modifiés après leur création. En revanche, les objets String sont immuables, et toute modification crée une nouvelle instance.
  2. Performance : Les opérations de modification avec StringBuilder et StringBuffer sont plus rapides que celles avec String. Cela est dû au fait que les modifications se font directement sur l’objet existant plutôt que de créer de nouvelles instances.
  3. Flexibilité : Les classes StringBuilder et StringBuffer offrent plus de flexibilité pour des opérations de modification fréquentes. Elles sont particulièrement utiles lorsque vous avez besoin d’ajouter, d’insérer, de remplacer ou de supprimer du texte de manière efficace.

1. Montrer la mutabilité de StringBuilder et StringBuffer

Exemple avec String (Immutabilité) :
public class ImmutableStringExample {
    public static void main(String[] args) {
        String str = "Hello";
        
        // Concaténation crée une nouvelle instance
        str = str + " World";
        
        System.out.println("Nouvelle chaîne : " + str);
    }
}

Dans cet exemple, la concaténation crée une nouvelle instance de String à chaque opération, car les chaînes sont immuables.

Pour vérifier que Java crée à chaque fois une nouvelle instance lors de la concaténation de chaînes avec l’opérateur ‘+’, vous pouvez utiliser la méthode System.identityHashCode() pour obtenir l’identifiant de hachage des objets String résultants. Si les identifiants de hachage sont différents à chaque concaténation, cela confirme que de nouvelles instances de chaînes sont créées.

Voici un exemple de méthode qui illustre cela :

public class Main {
    public static void main(String[] args) {
        String str1 = "Hello";
        String str2 = "World";
        String result1 = str1 + str2;
        String result2 = str1 + str2;

        System.out.println("Identifiant de hachage de result1: " + System.identityHashCode(result1));
        System.out.println("Identifiant de hachage de result2: " + System.identityHashCode(result2));
    }
}

Dans ce code, nous concaténons les mêmes chaînes str1 et str2 deux fois avec l’opérateur ‘+’. En utilisant System.identityHashCode(), nous obtenons les identifiants de hachage des deux résultats. Si Java crée une nouvelle instance de chaîne chaque fois que nous concaténons, les identifiants de hachage des résultats seront différents. Sinon, ils seront les mêmes.

En exécutant ce code, vous devriez constater que les identifiants de hachage de result1 et result2 sont différents, confirmant ainsi que de nouvelles instances de chaînes sont créées à chaque concaténation. Cela démontre l’immutabilité des objets String en Java et l’impact potentiel sur la consommation de mémoire et les performances de votre application.

Exemple avec StringBuilder (Mutabilité) :
public class StringBuilderExample {
    public static void main(String[] args) {
        StringBuilder stringBuilder = new StringBuilder("Hello");
        
        // L'opération de modification est faite sur le même objet
        stringBuilder.append(" World");
        
        System.out.println("Nouvelle chaîne : " + stringBuilder.toString());
    }
}

Avec StringBuilder, l’opération d’ajout se fait directement sur le même objet, modifiant son contenu sans créer de nouvelles instances à chaque opération.

Dans l’exemple ci-dessous, nous allons utiliser StringBuilder pour vérifier que Java ne crée pas de nouvelles instances à chaque fois :

public class Main {
    public static void main(String[] args) {
        String str1 = "Hello";
        String str2 = "World";
        
        StringBuilder builder1 = new StringBuilder();
        builder1.append(str1);
        builder1.append(str2);
        
        StringBuilder builder2 = new StringBuilder();
        builder2.append(str1);
        builder2.append(str2);

        System.out.println("Identifiant de hachage de builder1: " + System.identityHashCode(builder1.toString()));
        System.out.println("Identifiant de hachage de builder2: " + System.identityHashCode(builder2.toString()));
    }
}

Dans cet exemple, nous utilisons deux instances différentes de StringBuilder, builder1 et builder2. Nous ajoutons ensuite les mêmes chaînes str1 et str2 à chaque instance de StringBuilder. Enfin, nous obtenons les identifiants de hachage des chaînes résultantes converties en objets String à l’aide de toString().

En exécutant ce code, vous constaterez que les identifiants de hachage des chaînes résultantes, builder1 et builder2, seront différents, confirmant ainsi que de nouvelles instances de chaînes ne sont pas créées à chaque concaténation avec StringBuilder. Cela met en évidence l’efficacité de l’utilisation de StringBuilder pour la manipulation de chaînes en Java, par rapport à la concaténation de chaînes avec l’opérateur ‘+’.

2. Montrer la Performance de StringBuilder et StringBuffer

Pour mieux comprendre l’impact des performances, vous pouvez mesurer le temps d’exécution des opérations de modification avec chaque approche. Par exemple :

public class PerformanceComparison {
    public static void main(String[] args) {
        int iterations = 100000;
        
        // Utilisation de String
        long startTime = System.nanoTime();
        String str = "Hello";
        for (int i = 0; i < iterations; i++) {
            str = str + " World";
        }
        long endTime = System.nanoTime();
        System.out.println("Temps avec String : " + (endTime - startTime) + " nanosecondes");

        // Utilisation de StringBuilder
        startTime = System.nanoTime();
        StringBuilder stringBuilder = new StringBuilder("Hello");
        for (int i = 0; i < iterations; i++) {
            stringBuilder.append(" World");
        }
        endTime = System.nanoTime();
        System.out.println("Temps avec StringBuilder : " + (endTime - startTime) + " nanosecondes");

        // Utilisation de StringBuffer
        startTime = System.nanoTime();
        StringBuffer stringBuffer = new StringBuffer("Hello");
        for (int i = 0; i < iterations; i++) {
            stringBuffer.append(" World");
        }
        endTime = System.nanoTime();
        System.out.println("Temps avec StringBuffer : " + (endTime - startTime) + " nanosecondes");
    }
}

Vous constaterez probablement que l’utilisation de StringBuilder est la plus rapide, suivi de près par StringBuffer, tandis que l’utilisation de String est généralement la moins performante. Cela met en évidence l’avantage des classes mutables pour les opérations de modification fréquentes sur les chaînes de caractères.

3. Montrer la flexibilité de StringBuilder et StringBuffer

Les classes StringBuilder et StringBuffer sont des outils puissants pour la manipulation de chaînes en Java, offrant une flexibilité accrue par rapport à la concaténation de chaînes classique. Leur flexibilité réside dans leur capacité à effectuer des opérations de modification fréquentes sur les chaînes de caractères de manière efficace. Voici une explication détaillée de leur flexibilité :

Avec StringBuilder et StringBuffer, vous pouvez facilement ajouter du texte à une chaîne existante à l’aide de la méthode append(). Cette méthode permet d’ajouter du texte à la fin de la chaîne actuelle de manière efficace. Par exemple :

StringBuilder builder = new StringBuilder("Hello");
builder.append(" World");
System.out.println(builder.toString()); // Affiche : Hello World

Note : De même, StringBuffer offre la même fonctionnalité à travers la méthode append().

Pour montrer la flexibilité de StringBuilder et StringBuffer ,nous avons pris le cas d’ajout du texte, nous pouvons aussi trouver d’autres fonctionnalités qui montrent bien cette flexibilité dans cette partie Opérations de base avec StringBuilder et StringBuffer

Opérations de base avec StringBuilder et StringBuffer

Les opérations de base avec StringBuilder et StringBuffer sont similaires, car ces deux classes offrent des fonctionnalités presque identiques pour la manipulation de chaînes de caractères en Java. Voici les opérations de base que vous pouvez effectuer avec StringBuilder et StringBuffer :

1. Ajout de texte :

Vous pouvez ajouter du texte à la fin de la chaîne existante à l’aide de la méthode append(). Cette méthode permet d’ajouter du texte de manière efficace à la fin de la chaîne actuelle.

Exemple :

 // Utilisation de StringBuilder pour construire une chaîne
        StringBuilder stringBuilder = new StringBuilder("Hello");
        stringBuilder.append(" ").append("World").append("!");

        // Convertir le StringBuilder en String
        String resultFromBuilder = stringBuilder.toString();

        // Utilisation de StringBuffer pour construire une chaîne
        StringBuffer stringBuffer = new StringBuffer("Bonjour");
        stringBuffer.append(" ").append("le Monde").append("!");

        // Convertir le StringBuffer en String
        String resultFromBuffer = stringBuffer.toString();

        // Afficher les résultats
        System.out.println("Avec StringBuilder : " + resultFromBuilder);
        System.out.println("Avec StringBuffer : " + resultFromBuffer);
2. Insertion de texte :

Vous pouvez insérer du texte à n’importe quelle position dans la chaîne existante à l’aide de la méthode insert(). Cette méthode vous permet d’insérer du texte à l’index spécifié dans la chaîne actuelle.

Exemple :

StringBuilder stringBuilder = new StringBuilder("Hello");
stringBuilder.insert(3, " New");
System.out.println(stringBuilder.toString()); // Output: Hel New lo

StringBuffer stringBuffer = new StringBuffer("Hello");
stringBuffer.insert(3, " New");
System.out.println(stringBuffer.toString()); // Output: Hel New lo
3. Remplacement de texte :

Vous pouvez remplacer une partie spécifique d’une chaîne de caractères avec une autre à l’aide de la méthode replace(). Cette méthode vous permet de modifier efficacement des portions spécifiques de la chaîne selon vos besoins.

Exemple :

StringBuilder stringBuilder = new StringBuilder("Hello");
stringBuilder.replace(1, 4, "i");
System.out.println(stringBuilder.toString()); // Output: Hilo

StringBuffer stringBuffer = new StringBuffer("Hello");
stringBuffer.replace(1, 4, "i");
System.out.println(stringBuffer.toString()); // Output: Hilo
4. Suppression de texte :

Vous pouvez supprimer une partie spécifique de la chaîne de caractères à l’aide de la méthode delete(). Cette méthode vous permet de supprimer efficacement des caractères à partir de positions spécifiées dans la chaîne actuelle.

Exemple :

StringBuilder stringBuilder = new StringBuilder("Hello");
stringBuilder.delete(1, 4);
System.out.println(stringBuilder.toString()); // Output: Ho

StringBuffer stringBuffer = new StringBuffer("Hello");
stringBuffer.delete(1, 4);
System.out.println(stringBuffer.toString()); // Output: Ho
5. Inversion de la chaîne :

Vous pouvez inverser le contenu de la chaîne à l’aide de la méthode reverse(). Cette méthode inverse l’ordre des caractères dans la chaîne actuelle.

Exemple :

StringBuilder builder = new StringBuilder("Hello");
builder.reverse();
6. Conversion en chaîne de caractères :

Une autre fonctionnalité essentielle de StringBuilder et StringBuffer est leur capacité à convertir leur contenu en une chaîne de caractères de type String. Cette opération est réalisée à l’aide de la méthode toString(), qui retourne une représentation de la chaîne actuelle sous forme de String.

Exemple :

StringBuilder builder = new StringBuilder("Hello");
String str = builder.toString();
7. Concaténation de chaînes de caractères :

L’un des cas d’utilisation les plus courants de StringBuilder et StringBuffer est la concaténation efficace de plusieurs chaînes de caractères. Plutôt que d’utiliser l’opérateur de concaténation +, qui crée une nouvelle instance de chaîne à chaque opération, vous pouvez utiliser les méthodes append() de StringBuilder et StringBuffer pour ajouter des chaînes de caractères à la fin de la chaîne actuelle.

Exemple :

// Utilisation de StringBuilder pour concaténer des chaînes
        StringBuilder stringBuilder = new StringBuilder("Hello");
        stringBuilder.append(" ").append("World").append("!");

        // Convertir le StringBuilder en String si nécessaire
        String resultFromBuilder = stringBuilder.toString();

        // Utilisation de StringBuffer pour concaténer des chaînes
        StringBuffer stringBuffer = new StringBuffer("Bonjour");
        stringBuffer.append(" ").append("le Monde").append("!");

        // Convertir le StringBuffer en String si nécessaire
        String resultFromBuffer = stringBuffer.toString();

        // Afficher les résultats
        System.out.println("Avec StringBuilder : " + resultFromBuilder);
        System.out.println("Avec StringBuffer : " + resultFromBuffer);

Différence entre StringBuilder et StringBuffer

La principale différence entre StringBuilder et StringBuffer réside dans la synchronisation.

  1. StringBuilder : Cette classe fait partie du package java.lang et est introduite dans Java 5. Elle est non synchronisée, ce qui signifie qu’elle n’est pas thread-safe. Cela signifie qu’elle n’est pas conçue pour être utilisée dans un environnement multithread où plusieurs threads peuvent accéder et modifier la même instance de manière concurrente. En raison de son caractère non synchronisé, StringBuilder offre de meilleures performances que StringBuffer dans un environnement à un seul thread.
  2. StringBuffer : D’autre part, StringBuffer est également dans le package java.lang mais elle est présente depuis les premières versions de Java. Contrairement à StringBuilder, StringBuffer est synchronisée, ce qui la rend thread-safe. Cela signifie qu’elle peut être utilisée en toute sécurité dans un environnement multithread où plusieurs threads accèdent et modifient la même instance simultanément. Cependant, en raison de sa synchronisation, StringBuffer peut être légèrement moins performante que StringBuilder dans un environnement à un seul thread.

En résumé, si vous travaillez dans un environnement à un seul thread où la synchronisation n’est pas un problème, il est recommandé d’utiliser StringBuilder pour des performances optimales. Si vous travaillez dans un environnement multithread où la synchronisation est nécessaire pour garantir l’intégrité des données, vous devriez opter pour StringBuffer, même si cela peut entraîner une légère baisse de performances due à la synchronisation supplémentaire.

Synchronisation avec StringBuffer

StringBuffer est synchronisé, ce qui signifie qu’il est sûr pour une utilisation dans des environnements multithreadés. Cependant, cela peut entraîner une perte de performance dans un environnement où la synchronisation n’est pas nécessaire.

pour une meilleure compréhension. Dans cet exemple, nous aurons deux threads qui essaient d’ajouter des caractères à un objet StringBuffer simultanément.

Exemple de synchronisation avec StringBuffer :
public class StringBufferSynchronizationExample {
    public static void main(String[] args) {
        // Création d'un objet StringBuffer partagé
        StringBuffer synchronizedBuffer = new StringBuffer();

        // Opération d'ajout à effectuer par les threads
        Runnable appendTask = () -> {
            for (int i = 0; i < 5; i++) {
                // Synchronisation pour éviter les conflits
                synchronized (synchronizedBuffer) {
                    synchronizedBuffer.append(Thread.currentThread().getName());
                }
            }
        };

        // Création de deux threads effectuant des opérations simultanées
        Thread thread1 = new Thread(appendTask, "Thread1");
        Thread thread2 = new Thread(appendTask, "Thread2");

        // Démarrage des threads
        thread1.start();
        thread2.start();

        // Attendre la fin des threads
        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // Affichage du résultat
        System.out.println("Contenu de la chaîne synchronisée : " + synchronizedBuffer.toString());
    }
}

Explication détaillée :

  1. Création d’un objet StringBuffer : Nous créons un objet StringBuffer appelé synchronizedBuffer. Cet objet sera partagé entre les threads.
  2. Opération d’ajout (appendTask) : Nous définissons une opération d’ajout qui sera effectuée par les threads. Dans cet exemple, chaque thread essaie d’ajouter son nom (Thread1 ou Thread2) à l’objet synchronizedBuffer.
  3. Synchronisation avec synchronized : Nous utilisons un bloc synchronized pour encadrer l’opération d’ajout dans lequel chaque thread essaie d’ajouter son nom à la chaîne. Cela garantit que seule une opération peut être effectuée à la fois sur l’objet partagé, évitant ainsi les conflits.
  4. Création des threads et démarrage : Nous créons deux threads (Thread1 et Thread2) qui exécuteront l’opération d’ajout simultanément.
  5. Attente de la fin des threads : Nous utilisons thread1.join() et thread2.join() pour attendre que les deux threads aient terminé leur exécution avant de poursuivre.
  6. Affichage du résultat : Enfin, nous affichons le contenu de l’objet synchronizedBuffer après que les deux threads ont terminé leurs opérations.

Cet exemple illustre comment la synchronisation avec StringBuffer permet d’éviter les problèmes de concurrence lorsqu’il y a plusieurs threads qui tentent d’effectuer des opérations sur le même objet simultanément. La section synchronisée garantit que chaque thread a un accès exclusif à l’objet partagé.

Quiz de ce tuto

Vous pouvez tester que vous avez bien assimiler tous ce que nous avons appris ensemble via ce quiz 🙂 🙂 amusez vous bien.

/10
0 votes, 0 avg
6
Créé le

Quiz JAVA SE : StringBuilder ET StringBuffer

Ce quiz vous aide à améliorer vos connaissances en Java SE 🙂 🙂 

1 / 10

1. Quelle méthode est utilisée pour obtenir la longueur actuelle d'un StringBuilder ou StringBuffer ?

2 / 10

2. Quelle méthode est utilisée pour inverser le contenu d'un StringBuilder ou StringBuffer ?

3 / 10

3. Quelle méthode est utilisée pour ajouter du texte à la fin d'un StringBuilder ou StringBuffer ?

4 / 10

4. Quelle classe est non synchronisée et offre de meilleures performances dans un environnement à un seul thread ?

5 / 10

5. Quelle classe est synchronisée et garantit la thread-safety, mais peut être légèrement moins performante ?

6 / 10

6. Quelle méthode est utilisée pour supprimer une partie spécifique d'un StringBuilder ou StringBuffer ?

7 / 10

7. Quelle méthode est utilisée pour remplacer une partie spécifique d'un StringBuilder ou StringBuffer ?

8 / 10

8. Quelle méthode est utilisée pour obtenir la représentation de chaîne de caractères d'un StringBuilder ou StringBuffer ?

9 / 10

9. Quelle méthode est utilisée pour insérer du texte à une position spécifique dans un StringBuilder ou StringBuffer ?

10 / 10

10. Quelle classe est utilisée pour manipuler efficacement des chaînes de caractères de manière mutable en Java ?

Votre note est de

0%

Veuillez évaluer ce quiz

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *