Rechercher
 

Manipulation de chaînes de caractères en Java

Manipulation de caractères Les types de données en Java



Accès rapide :
   La vidéo
   Rappels sur les standards d'encodage de caractères
   Utilisation du type java.lang.String
   Séquences de caractères particulières
   Comparaison de chaînes de caractères
   Quelques méthodes de traitement de chaînes de caractères
   Conversions types primitifs / chaînes de caractères

La vidéo

Cette vidéo vous montre comment utiliser les chaînes de caractères en Java. On y insiste sur l'aspect immuable des chaînes de caractères Java ainsi que sur la manière de correctement comparer deux chaînes. Quelques méthodes de la classe String vous sont aussi présentées.


Utilisation de chaînes de caractères en Java

Rappels sur les standards d'encodage de caractères

Pour un rappel sur les standards d'encodage de caractères, je vous renvoie vers le chapitre précédent qui traite de ce sujet : activez ce lien pour consulter ce chapitre.

Utilisation du type java.lang.String

Une chaîne de caractères s'introduit par le type String. L'ensemble des caractères de la chaîne sont compris entre deux double-guillemets. Voici un exemple de déclaration de chaînes de caractères.

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
public class Demo {
 
    public static final void main( String [] args ) {

        String firstName = "Diego";
        String lastName = "De La Vega";
        
        System.out.println( firstName + " - " + lastName );

    }
               
}
Exemple de déclaration de chaînes de caractères

En fait le type String peut aussi s'écrire java.lang.String. Bien entendu, l'informaticien (étant fainéant), préferera le plus souvent la première approche. Voici un exemple de code montrant cette seconde écriture faisant apparaître le paquetage java.lang (la classe String est contenu dans le paquetage java.lang).

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
public class Demo {
 
    public static final void main( String [] args ) {

        java.lang.String firstName = "Diego";
        java.lang.String lastName = "De La Vega";
        
        System.out.println( firstName + " - " + lastName );

    }
               
}
Exemple de déclaration de chaînes de caractères, en spécifiant le paquetage
normalement, l'écriture courte du première exemple est autorisée à condition d'importer le type via le mot clé import. Néanmoins, le paquetage java.lang est visible par défaut. D'où le fait que vous puissiez utiliser la notation courte sans utilisation du mot clé import.

Contrairement aux types étudiés précédemment (int, long, float, double, boolean, ...), vous aurez noté que le type String commence par une majuscule. Cette remarque est pertinente. Les types commençant par une minuscule (int, ...) sont appelés types primitifs (ou parfois types scalaires). Les types commençant par des majuscules sont appelés types objets (classes, interfaces, enums, ...). Dans le cas de String, nous avons plus précisément à faire à une classe.

Pour l'heure, nous noterons qu'une seule différence entre types primitifs et types objets : les types objets exposent des méthodes, en quelques sortes des fonctions, alors que les types primitifs n'en exposent pas. A titre d'exemple, notez l'utilisation des méthodes toLowerCase et toUpperCase dans le code suivant.

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
public class Demo {
 
    public static final void main( String [] args ) {

        String firstName = "Diego";
        String lastName = "De La Vega";
        
        System.out.println( firstName.toLowerCase() + " - " + lastName.toUpperCase() );

    }
               
}
Exemple de déclaration de chaînes de caractères

Comme vous le constatez sur l'exemple ci-dessus, il est possible de concaténer des chaînes de caractères avec l'opérateur +. Il est aussi possible d'utiliser l'opérateur +=, comme le montre ce nouvel exemple.

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
 14 
public class Demo {
 
    public static final void main( String [] args ) {

        String firstName = "Diego".toLowerCase();
        String lastName = "De La Vega".toUpperCase();
        String fullString = firstName + " " + lastName;
        fullString += " !";
        
        System.out.println( fullString );       // Affiche : diego DE LA VEGA !

    }
               
}
Concaténations de chaînes de caractères

Séquences de caractères particulières

Tout comme nous l'avons vu, dans le chapitre précédent sur l'utilisation de caractères, il existe des séquences particulières permettant d'utiliser des caractères spéciaux ou non accessibles à partir de votre clavier.

Un retour à la ligne : \n
 String str = "Hello\n";
Une tabulation : \t
 String str = "First\tSecond";
Une double guillemet : \"
 String str = "Un \" au milieu";
Un caractère : \\
 String str = "C:\\Folder\\file.txt";
Utilisation de la notation unicode de Java
(sur 4 digits et en hexadécimal)
 String str = "\u03c0 vaut environ 3.141592654";  // Un caractère PI en minuscule
Utilisation de caractères spéciaux
 char c1 = '\n';    // Un retour à la ligne
 char c2 = '\t';    // Une tabulation
 char c3 = '\\';    // Tout simplement un \
 char c4 = '\'';    // Un caractère '
selon la configuration de votre système d'exploitation, il est possible que le caractère PI ne s'affiche pas correctement. Effectivement, faut-il que vous ayez une police de caractères connaissant les glyphes de caractères que vous utilisez (ici un caractère Grec). Normalement, sous Linux, les choses se passent bien. Dans le cas contraire, installez (ou utilisez) une police de caractères compatible Unicode.

Comparaison de chaînes de caractères

L'opérateur == peut être utilisé entre deux chaînes de caractères. Pour autant il ne va pas forcément calculer ce à quoi vous vous attendez. A titre d'exemple, exécutez ce code.

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
 14 
 15 
public class Demo {
            
    public static void main( String [] args ) {
    
        String first = "toto";
        String temp = "to";
        String second = temp + temp;
        
        if ( first == second ) {
            System.out.println( "Les deux chaînes sont identiques" );
        }
    
    }
    
}
Ce programme ne produira aucun affichage.

Comme vous l'avez certainement constaté, aucun affichage n'est produit : c'est normal. L'opérateur == utilisé sur des types objets (ici nos chaînes de caractères) ne regarde pas si les caractères des deux chaînes sont égaux deux à deux. Ce qu'il vérifie, c'est si les deux pointeurs (les deux adresses en mémoire) des deux variables first et second sont égaux ou non. Dit autrement on regarde si les deux variables pointent au même endroit en mémoire, si c'est le même objet.

En effet, toutes les variables basées sur des types objets (des types qui commencent par une majuscule, comme String) sont en fait des pointeurs (des adresses en mémoire) qui référencent des objets. Le meilleur moyen de valider qu'une chaîne de caractères est un pointeur et de compiler le programme suivant qui initialise str à l'adresse 0 (le pointeur nul). On spécifie une adresse initialisée à 0 en utilisant le mot clé réservé null. Comme tout mot clé réservé du langage, null doit s'écrire en minuscule.

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
public class Demo {
            
    public static void main( String [] args ) {
    
        String str = null;
        System.out.println( str );
    
    }
    
}
Mise en évidence que str est un pointeur.

Du coup, la question que vous devez avoir en tête est la suivante : ok, mais comment comparer deux chaînes de caractères entre elles ? En fait, il vous faut utiliser une méthode de la classe String : la méthode equals. Analysez le code suivant et essayez de déduire les affichages qu'il produit.

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
 20 
 21 
 22 
 23 
 24 
 25 
 26 
public class Demo {
            
    public static void main( String [] args ) {

        String temp = "to";
    
        String first = "toto";
        String second = temp + temp;
        String third = first;           // Copie de pointeur (aucune duplication de chaîne)
        String fourth = "toto";
        
        System.out.println( first == second );     
        System.out.println( first.equals( second ) );     

        System.out.println( first == third );     
        System.out.println( first.equals( third ) );     
    
        System.out.println( first == fourth );     
        System.out.println( first.equals( fourth ) );     

        System.out.println( first == "Java" );     
        System.out.println( first.equals( "Java" ) );     

    }
    
}
Quelques exemples de comparaisons (de pointeurs ou de chaînes de caractères)

Nous allons maintenant vérifier vos déductions, avec l'affichage produit par le programme ci-dessus.

$> javac Demo.java
$> java Demo
false
true
true
true
true
true
false
false
$>
la ligne 9 effectue une copie de pointeur : third et first pointent donc au même endroit en mémoire. On compare donc first à lui-même sur les lignes 15 et 16.
la ligne 18 de l'exemple de code produit un résultat qui peut vous surprendre. Néanmoins le résultat proposé est bien le bon. En effet, le compilateur joue une optimisation : une chaîne de caractères apparaissant plusieurs fois dans un fichier de code Java sera stockée dans le .class en un unique exemplaire. Cela explique que l'opérateur == renvoie true sur la comparaison considérée. Du coup, l'appel à equals renverra aussi true car on compare la même donnée en mémoire.
donc, la comparaison de deux chaînes de caractères peut vous poser problème si vous ne la gérez pas correctement. Il faut utiliser la méthode equals et non pas l'opérateur ==.

Quelques méthodes de traitement de chaînes de caractères

la classe String est implémentée de manière à produire des objets (des chaînes de caractères) immuables (on dit aussi parfois immutables). Une fois une chaîne produite, il n'est plus possible de changer son état (son contenu). Par contre, diverses méthodes permettent de produire de nouvelles chaînes de caractères modifiées à partir d'une chaîne originale. Notez enfin, qu'une variable de type String peut être réaffectée sur une nouvelle chaîne modifiée.

La conséquence directe de la remarque précédente, est que toute méthode de transformation de chaînes de caractères proposé par la classe String renvoient un résultat de type String : la nouvelle chaîne de caractère modifiée.

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
public class Demo {
            
    public static void main( String [] args ) {
    
        String original = "Diego De La Vega";
        String tranformation = original.toUpperCase();
        
        System.out.println( transformation );                       // Affiche : DIEGO DE LA VEGA
        System.out.println( "Compact Sample".toLowerCase() );       // Affiche : compact sample
            
    }
    
}
Transformation de chaînes de caractères

Comme indiqué dans la note, il est possible de réaffecter le résultat d'une transformation à la variable, comme le montre l'exemple suivant.

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
public class Demo {
            
    public static void main( String [] args ) {
    
        String zorro = "Diego De La Vega";
        zorro = zorro.toLowerCase();
        
        System.out.println( zorro );           // Affiche : diego de la vega
            
    }
    
}
Transformation de chaînes de caractères

Le tableau suivant propose quelques méthodes utiles proposées par la classe String.

Nom de la méthode Description Exemple d'utilisation
int indexOf( String subString ); Recherche de la présence d'une sous-chaîne dans la chaîne d'origine. Renvoie -1 si la sous chaine n'est pas présente. Sinon, l'indice de la première occurrence trouvée est renvoyé. Attention, les indices commencent à 0 (d'où le -1 en cas d'échec).
int l = "abcdef".indexOf( "cd" );  // 2
int l = "abcdef".indexOf( "gh" );  // -1
int lastIndexOf( String subString ); Recherche de la présence d'une sous-chaîne dans la chaîne d'origine. Renvoie -1 si la sous chaine n'est pas présente. Sinon, l'indice de la dernière occurrence trouvée est renvoyé. Attention, les indices commencent à 0 (d'où le -1 en cas d'échec).
int l = "abcdef".indexOf( "cd" );  // 2
int l = "abcdef".indexOf( "gh" );  // -1
int length(); Calcule la taille de la chaîne de caractères
int l = "toto".length();  // 4
String replace( CharSequence target, CharSequence replacement ); Remplace toutes les occurrences de target par replacement.
String str = "abcdabcd".replace( "b", "e" );
System.out.println( str ); // aecdaecd
String [] split( String pattern ); Découpe une chaîne de caractères en sous-chaînes à partir d'un séparateur (plus ou moins complexe).
String [] parts = "19/01/2018".split( "/" );
System.out.println( parts[0] );  // 19
System.out.println( parts[1] );  // 01
System.out.println( parts[2] );  // 2018
String substring( int first, int afterLast ); Extrait une sous chaîne de caractères. Attention, le second paramètre doit être fixé à 1 de plus que l'indice de dernier caractère à extraire. Les indices doivent commencer à 0.
String str = "abcdef".substring( 2, 4 );  // cd
String trim(); Enlève les blancs (espaces, tabulations) devant et derrière la chaîne.
String str = "  Toto  ".toLowerCase();  // Toto
String toLowerCase(); Transforme la chaîne de caractères en minuscules
String str = "Toto".toLowerCase();  // toto
String toUpperCase(); Transforme la chaîne de caractères en majuscules
String str = "Toto".toUpperCase();  // TOTO
ce tableau n'est pas exhaustif et de nombreuses autres méthodes existent. Nous y reviendrons progressivement au fur et à mesure de la progression de ce tutoriel. Pour les plus impatients, je vous propose de consulter la Javadoc.
la méthode split prend en paramètre un pattern pour le découpage de la chaîne de caractère. Ce pattern est en fait une expression régulières. Le formalisme utilisé par les expressions régulière est en fait extrêmement puissant : il me faudrait plusieurs heures pour vous expliquer toutes les subtilités qui vous sont offertes. Nous reviendrons ultérieurement sur ce formalisme. Pour le moment, l'exemple proposé est très simple : le caractère / sert de séparateur.

Voici un petit exemple d'utilisation de méthodes de la classe String.

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
 20 
 21 
 22 
 23 
 24 
 25 
 26 
 27 
 28 
public class Demo {
            
    public static void main( String [] args ) {
    
        String message = "This is a String with Unicode characters (\u03c0)";
        System.out.println( message );
        
        String upper = message.toUpperCase();
        System.out.println( upper );
        String lower = message.toLowerCase();
        System.out.println( lower );
        System.out.println( message );
        
        String subPart = message.substring( 22, 29 );
        System.out.println( subPart + "!" );
        
        String [] parts = message.split( " " );
        for (String str : parts) {
            System.out.print( str + " - " );
        }
        System.out.println();
        
        String replacement = message.replace( "String", "Truc" );
        System.out.println( replacement );            

    }
    
}
Exemple d'utilisation de méthodes de la classe String

Conversions types primitifs / chaînes de caractères

Il est possible de convertir des valeurs numériques (de type int, long, float, double, ...) en chaînes de caractères et réciproquement. Idem pour les booléen. Pour ce faire, il faut utiliser les méthodes statiques proposées par la classe enveloppante (Wrapped Class) associée à chaque type primitif. Le tableau suivant précise le nom de ces classes

Nom du type primitif Nom de la classe associée
byte java.lang.Byte
short java.lang.Short
int java.lang.Integer
long java.lang.Long
float java.lang.Float
double java.lang.Double
char java.lang.Character
boolean java.lang.Boolean
comme le paquetage java.lang est importé par défaut, l'utilisation du préfixe n'est pas obligatoire.

Voici un exemple d'utilisation de ces classes.

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
 20 
 21 
public class Demo {
            
    public static void main( String [] args ) {
    
        String strValue = "123";
        int value = Integer.parseInt( strValue );
        strValue = "3.141592654";
        double value2 = Double.parseDouble( strValue );
        System.out.println( value + " - " + value2 );
        
        String finalString = value + "";
        finalString += " ";                         
        finalString += Double.toString( value2 );
        System.out.println( finalString );
        
        // Exemple d'affichage formaté : les différents formats seront vus dans un prochain chapitre
        String strFinal2 = String.format( "%05d [%05.2f]", value, value2 );
        System.out.println( strFinal2 );
    }
    
}
Exemples de conversions

Et voici le résultat produit par cet exemple.

$> javac Demo.java
$> java Demo
123 - 3.141592654
123 3.141592654
00123 [03,14]
$> 


Manipulation de caractères Les types de données en Java