Implémenter les chaînes de caractères avec la classe String

Implémenter les chaînes de caractères avec la classe String

Conceptuellement, les chaînes de caractères Java sont des séquences de caractères Unicode. Par exemple, la chaîne de caractères “Java\u2122” se compose des cinq caractères Unicode J, a, v, a et ™.

Java n’a pas de type de chaîne de caractères intégré. Au lieu de cela, la bibliothèque Java standard contient une classe prédéfinie appelée, naturellement, String. Chaque chaîne de caractères citée est une instance de la classe String :

String e = ""; // une chaîne de caractères vide
String greeting = "Bonjour";

Sous-chaînes de caractères en Java

Vous pouvez extraire une sous-chaîne de caractères à partir d’une chaîne de caractères plus longue avec la méthode substring de la classe String. Par exemple,

String greeting = "Bonjour" ;
String s = greeting.substring(0, 3) ;

crée une chaîne de caractères composée des caractères “Bon”.

Comme C et C++, Java compte les éléments d’une chaîne de caractères en commençant par 0. Le premier paramètre de la méthode substring est le numéro du premier caractère à copier.

Le deuxième paramètre est le numéro de la première position qu’on veut pas copier. Dans notre cas, nous voulons copier les positions 0, 1 et 2 (de la position 0 à la position 2 inclusivement).

Comme la méthode substring le compte, cela signifie de la position 0 inclusivement à la position 3 exclusive.

Il y a un avantage dans la façon dont la méthode substring fonctionne : Le calcul de la longueur de la sous-chaîne est facile. La chaîne s.substring(a, b) a toujours la longueur b – a. Par exemple, la chaîne “Bon” a la longueur 3 – 0 = 3.

Concaténation de deux chaînes de caractères en Java

Java, comme la plupart des langages de programmation, vous permet d’utiliser le symbole “+” pour joindre (concaténer) deux chaînes.

String expletive = "Expletive";
String PG13 = "deleted";
String message = expletive + PG13;

Le code précédent définit la variable message à la chaîne de caractères “Expletivedeleted”. (Notez l’absence d’espace entre les mots : L’opérateur + joint deux chaînes de caractères dans l’ordre de réception, exactement comme elles sont données.

Lorsque vous concaténez une chaîne de caractères avec une valeur qui n’est pas une chaîne de caractères, cette dernière est convertie en chaîne de caractères. Comme pouvez le dans la série d’articles sur l’héritage, chaque objet Java peut être converti en chaîne. Par exemple,

int age = 13;
String rating = "PG" + age;

définit la variable rating à la chaîne de caractères “PG13”.

Cette fonction est couramment utilisée dans les instructions print. Par exemple, l’instruction

System.out.println("La réponse est " + reponse);

est parfaitement acceptable et affiche ce vous attendez (et avec un espacement correct en raison de l’espace après le mot “est”).

Si vous avez besoin d’assembler plusieurs chaînes de caractères séparées par un délimiteur, utilisez la méthode de jonction statique :

String all = String.join(" / ", "S", "M", "L", "XL"); // Tout est la chaîne de caractères "S / M / L / XL"

A partir de Java 11, il existe une méthode de répétition :

String repetee = "Java".repeat(3) ; // la valeur de repetee est "JavaJavaJava".

Les chaînes de caractères sont immuables en Java

La classe String ne donne aucune méthode permettant de modifier un caractère dans une chaîne existante. Si vous voulez transformer la variable greeting en “bonheur”, vous ne pouvez pas changer directement les caractères “j” et “o” de greeting en “h” et “e”, respectivement.

Comment allons-nous modifier la chaîne de caractères ? En Java, c’est très simple : Concaténez la sous-chaîne de caractères que vous voulez conserver avec les caractères par lesquelles vous voulez remplacer ceux à abandonner.

greeting="Hello";
greeting = greeting.substring(0, 3) + "p!";

Cette déclaration change la valeur actuelle de la variable greeting en “Help!”.

Comme vous ne pouvez pas modifier les caractères individuels d’une chaîne Java, la documentation fait référence aux objets de la classe String comme étant immuables. Tout comme le chiffre 3 est toujours 3, la chaîne “Hello” contiendra toujours la séquence d’unités de code pour les caractères H, e, l, l, o.

Vous ne pouvez pas modifier ces valeurs. Pourtant, vous pouvez, comme vous venez de le voir, changer le contenu de la variable chaîne de caractères greeting et le faire se référer à une chaîne différente, tout comme vous pouvez faire une variable numérique contenant actuellement la valeur 3 tenir la valeur 4.

N’est-ce pas beaucoup moins efficace ? Il semblerait plus simple de changer les unités de code que de construire une toute nouvelle chaîne à partir de zéro. Eh bien, oui et non.

En effet, il n’est pas efficace de générer une nouvelle chaîne qui contient la concaténation de “Hel” et “p!” mais les chaînes de caractères immuables ont un grand avantage: Le compilateur peut organiser le partage des chaînes de caractères.

Dans l’ensemble, les concepteurs de Java ont décidé que l’efficacité du partage l’emportait sur l’inefficacité de l’édition des chaînes de caractères en extrayant des sous-chaînes de caractères et en les concaténant à d’autres chaînes de caractères.

Regardez vos propres programmes ; nous imaginons que la plupart du temps, vous ne changez pas de chaîne de caractères – vous n’avez qu’à les comparer.

Il y a une exception commune : l’assemblage de chaînes de caractères à partir de caractères individuels ou de chaînes plus courtes provenant du clavier ou d’un fichier.

Pour ces situations, Java fournit une classe séparée que nous décrivons dans la section “Construire des chaines de caractères”).

Les programmeurs C sont généralement déconcertés lorsqu’ils voient des chaînes Java pour la première fois parce qu’ils considèrent les chaînes comme des tableaux de caractères :

char greeting[] = "Hello";

C’est une mauvaise analogie : Une chaîne Java est en gros analogue à un pointeur char*,

char* greeting = "Hello";

Lorsque vous remplacez greeting par une autre chaîne de caractères, le code Java fait à peu près ce qui suit :

char* temp = malloc(6);
strncpy(temp, greeting, 3);
strncpy(temp + 3, "p!", 3);
greeting = temp;

Bien sûr, maintenant greeting pointe sur la chaîne de caractères “Help!” et même le programmeur C le plus aguerri doit admettre que la syntaxe Java est plus agréable qu’une séquence d’appels strncpy. Et si on faisait un autre affectation à greeting ?

greeting = "Howdy";

N’avons-nous pas une fuite de mémoire? Après tout, la chaîne de caractères originale a été ajoutée dans la mémoire tampon.

Heureusement, Java fait la collecte automatique des objets inutiles. Si un bloc de mémoire n’est plus nécessaire, il sera éventuellement supprimé de la mémoire.

Si vous êtes un programmeur C++ et utilisez la classe string définie par ANSI C++, vous serez beaucoup plus à l’aise avec le type String Java.

Les objets de chaîne de caractères C++ exécutent également l’allocation et la désallocation automatiques de la mémoire. La gestion de la mémoire est effectuée explicitement par les constructeurs, les opérateurs d’affectation et les destructeurs.

Cependant, les chaînes de caractères C++ sont mutables – vous pouvez modifier des caractères individuels dans une chaîne de carcatères.

Tester l’égalité de deux chaînes de caractères en Java

Pour tester si deux chaînes de caractères sont égales, utilisez la méthode equal(). L’expression s.equal(t) retourne true si les chaînes s et t sont égales, false sinon. Notez que s et t peuvent être des variables de chaîne de caractères ou des littéraux de chaîne.

Par exemple, l’expression “Bonjour”.equals(salut) est parfaitement légal. Pour tester si deux chaînes de caractères sont identiques à l’exception de la distinction majuscule/minuscules, utilisez la méthode equalsIgnoreCase.

"Hello".equalsIgnoreCase("hello");

N’utilisez pas l’opérateur == pour tester si deux chaînes sont égales ! Il détermine seulement si les chaînes de caractères sont stockées ou non dans le même emplacement.

Bien sûr, si les chaînes de caractères sont au même endroit, elles doivent être égales. Mais il est tout à fait possible de stocker plusieurs copies de chaînes identiques à des endroits différents.

String greeting = "Hello";// initialiser le message d'accueil à une chaîne de caractères
if (greeting == "Hello") . . .
//Probablement vrai
if (greeting.substring(0, 3) == "Hel") . . .
// Probablement faux

Si la machine virtuelle organise toujours le partage de chaînes de caractères égales, vous pouvez utiliser l’opérateur == pour tester l’égalité.

Mais seules les chaînes de caractères littérales sont partagées, pas les chaînes qui sont le résultat d’opérations comme “+” ou substring. Par conséquent, n’utilisez jamais == pour comparer les chaînes de caractères.

Sinon, vous pouvez vous retrouver avec un programme avec le pire type de bogue – un bogue intermittent qui semble se produire de façon aléatoire.

Les programmeurs C n’utilisent jamais == pour comparer des chaînes de caractères mais utilisent la fonction strcmp. La méthode Java compareTo est l’analogue exact de strcmp. Vous pouvez utiliser

if (greeting.compareTo("Hello") == 0) . . .

mais il semble plus clair d’utiliser equals() à la place.

Les chaînes de caractères vides ou nulles en Java

La chaîne vide “” est une chaîne de caractères de longueur 0, vous pouvez tester si une chaîne est vide en appelant

if (str.length() == 0)
ou
if (str.equal(""))

Une chaîne vide est un objet Java qui contient la longueur de la chaîne (à savoir 0) et un contenu vide. Cependant, une variable String peut aussi contenir une valeur spéciale, appelée null, qui indique qu’aucun objet n’est actuellement associé à la variable.

Pour tester si une chaîne de caractères est nulle, utilisez l’instruction if (str === null). Parfois, vous devez tester qu’une chaîne n’est ni nulle ni vide. Pour ce faire, utilisez l’instruction

if (str != null && str.length() != 0)

Vous devez d’abord tester que str n’est pas nulle. Comme vous le verrez dans la série d’articles sur les objets et classes en Java, c’est une erreur d’invoquer une méthode sur une valeur nulle.

Points de code et unités de code

Les chaînes de caractères en Java sont des séquences de valeurs de type char. Comme nous l’avons vu dans l’article sur les types de données en Java. Le type de données char est une unité de code pour représenter les points de code Unicode dans le codage UTF-16.

Les caractères Unicode les plus couramment utilisés peuvent être représentés avec une seule unité de code. Les caractères supplémentaires nécessitent une paire d’unités de code.

La méthode length() donne le nombre d’unités de code nécessaires pour une chaîne donnée dans le codage UTF-16. Par exemple :

String greeting = "Hello";
int n = greeting.length(); // est 5

Pour obtenir la longueur réelle, c’est-à-dire le nombre de points de code, il faut appeler

int cpCount = saling.codePointCount(0, greeting.length()) ;

L’appel s.charAt(n) renvoie l’unité de code à la position n, où n est entre 0 et s.length() – 1. Par exemple :

char first = greeting.charAt(0); // premier est 'H'.
char last = greeting.charAt(4); // le dernier est 'o'.

Pour arriver au ième point de code, utilisez les lignes suivantes

int index = greeting.offsetByCodePoints(0, i);
int cp = greeting.codePointAt(index);

 

Pourquoi on fait tout un plat des unités codées ? Réfléchissez à la phrase
 est l’ensemble des octonions.
Le caractère (U+1D546) nécessite deux unités de code dans le codage UTF-16. Appeler

char ch = phrase.charAt(1);

ne retourne pas d’espace mais la deuxième unité de code de . Pour éviter ce problème, vous ne devez pas utiliser le type char. C’est un niveau de programmation trop bas.

Ne pensez pas que vous pouvez ignorer les caractères exotiques avec des unités de code au-dessus de U+FFFF. Vos utilisateurs qui aiment les émojis peuvent mettre des caractères tels que (U+1F37A, chope à bière) dans des chaînes de caractères.

Si votre code traverse une chaîne de caractères, et que vous voulez regarder chaque point de code à tour de rôle, vous pouvez utiliser ces instructions :

int cp = sentence.codePointAt(i);
if (Character.isSupplementaryCodePoint(cp)) i += 2;
else i++;

Vous pouvez revenir en arrière avec les instructions suivants :

i--;
if (Character.isSurrogate(sentence.charAt(i))) i--;
int cp = sentence.codePointAt(i);

Évidemment, c’est très douloureux. Une façon plus simple est d’utiliser la méthode codePoints qui donne un “flux” de valeurs int, une pour chaque point de code. Vous pouvez simplement transformer le flux en un tableau et le parcourir.

int[] codePoints = str.codePoints().toArray();

Inversement, pour transformer un tableau de points de code en une chaîne de caractères, utilisez un constructeur.

String str = new String(codePoints, 0, codePoints.length);

La machine virtuelle n’a pas besoin d’implémenter des chaînes de caractères sous forme de séquences d’unités de code. En Java 9, les chaînes qui ne contiennent que des unités de code à un octet utilisent un tableau d’octets, et toutes les autres utilisent un tableau de caractères.

L’API String de chaîne de caractères

La classe String en Java contient plus de 50 méthodes. Un nombre étonnamment important d’entre eux sont suffisamment utiles pour que nous puissions imaginer les utiliser fréquemment.

Voici les descriptions de quelques méthodes de la classe String:

char charAt(int index): retourne l’unité de code à l’emplacement spécifié. Vous ne voulez probablement pas appeler cette méthode à moins d’être intéressé par les unités de code de bas niveau.

int codePointAt(int index): retourne le point de code qui commence à l’endroit spécifié par index.

int offsetByCodePoints(int startIndex, int cpCount): retourne l’index du point de code de cpCount éloigné du point de code à startIndex.

int compareTo(String other): retourne une valeur négative si la chaîne vient avant other dans l’ordre du dictionnaire, une valeur positive si la chaîne vient après other dans l’ordre du dictionnaire, ou 0 si les chaînes sont égales.

IntStream codePoints(): retourne les points de code de cette chaîne sous forme de flux (stream). Appeler toArray pour les mettre dans un tableau.

new String(int[] codePoints, int offset, int count): construit une chaîne avec le nombre count de points de code dans le tableau à partir de l’indice offset.

boolean empty()

boolean blank(): retourne true si la chaîne est vide ou est constituée d’espaces.

boolean equals(Object other): retourne true si la chaîne est égale à other.

boolean equalsIgnoreCase(String other): retourne true si la chaîne est égale à other, sauf pour la différenciation majuscule/minuscules.

boolean startsWith(String prefix)

boolean endsWith(String suffix): retourne true si la chaîne commence ou se termine par un suffix.

int indexOf(String str)

int indexOf(String str, int fromIndex)

int indexOf(int cp)

int indexOf(int cp, int fromIndex): retourne le début de la première chaîne de caractères égale à la chaîne de caractères str ou au point de code cp, à partir de l’index 0 ou de fromIndex, ou -1 si str ne figure pas dans cette chaîne.

int lastIndexOf(String str)

int lastIndexOf(String str, int fromIndex)

int lastindexOf(int cp)

int lastindexOf(int cp, int fromIndex): retourne le début de la dernière chaîne de caractères égale à la chaîne de caractères str ou au point de code cp, en commençant à la fin de la chaîne ou à fromIndex.

int length(): retourne le nombre d’unités de code de la chaîne de caractères.

int codePointCount(int startIndex, int endIndex): renvoie le nombre de points de code entre startIndex et endIndex – 1.

String replace(CharSequence oldString, CharSequence newString): retourne une nouvelle chaîne qui est obtenue en remplaçant toutes les chaînes de caractères correspondant à la chaîne oldString par la chaîne newString. Vous pouvez fournir des objets String ou StringBuilder pour les paramètres CharSequence.

String substring(int beginIndex): retourne la chaîne à partir de l’index beginIndex spécifié jusqu’à la fin de la chaîne.

String substring(int beginIndex, int endIndex): retourne une nouvelle chaîne composée de toutes les unités de code depuis beginIndex jusqu’à la fin de la chaîne ou jusqu’à endIndex – 1.

String toLowerCase(): convertit les caractères d’une chaîne de caractères en minuscules.

String toUpperCase(): retourne une nouvelle chaîne de caractères contenant tous les caractères de la chaîne originale, les caractères majuscules étant convertis en minuscules, ou les caractères minuscules convertis en majuscules.

String trim(): élimine les espaces en début et en fin de la chaîne de caractères.

String strip(): retourne une nouvelle chaîne de caractères en éliminant tous les caractères de début et de fin qui sont ≤ U+0020 (trim) ou espaces blancs (strip) dans la chaîne originale.

String join(CharSequence delimiter, CharSequence… elements): retourne une nouvelle chaîne de carcatères joignant tous les éléments avec le délimiteur donné.

String repeat(int count): retourne la chaîne de caractères répètée count fois.

Construire des chaînes de caractères avec StringBuilder et StringBuffer

De temps en temps, vous avez besoin de construire des chaînes de caractères à partir de chaînes plus courtes, telles que des frappes de touches ou des mots d’un fichier. Il serait inefficace d’utiliser la concaténation de chaînes de caractères à cette fin.

Chaque fois que vous concaténez des chaînes de caractères, un nouvel objet String est construit. C’est une perte de temps et de mémoire.

L’utilisation de la classe StringBuilder contourne ce problème. Suivez ces étapes si vous avez besoin de construire une chaîne de caractères à partir de plusieurs petits morceaux. Tout d’abord, créez un constructeur de chaînes vide :

StringBuilder builder = new StringBuilder();

Chaque fois que vous avez besoin d’ajouter une autre partie, appelez la méthode append.

builder.append(ch); // ajoute un seul caractère
builder.append(str); // ajoute une chaîne de caractères

Lorsque vous avez fini de construire une chaîne de caractères, appelez la méthode toString. Vous obtiendrez un objet String avec la séquence de caractères contenue dans le constructeur.

String completedString = builder.toString();

La classe StringBuilder a été introduite en Java 5. Son prédécesseur, StringBuffer, est légèrement moins efficace, mais il permet à plusieurs threads d’ajouter ou de supprimer des caractères.

Si toute l’édition des chaînes de caractères se produit dans un seul thread (ce qui est généralement le cas), vous devriez utiliser StringBuilder à la place de StringBuffer.

Les API des deux classes sont identiques. Voici une liste de méthodes les plus importantes pour la classe StringBuilder.

StringBuilder(): constructs an empty string builder.

int length(): retourne le nombre d’unités de code du constructeur ou du tampon.

StringBuilder append(String str): ajoute une chaîne de caractères à la fin et renvoie la chaîne de caractères résultante.

StringBuilder append(char c): ajoute un caractère à la fin et renvoie la chaîne de caractères résultante.

StringBuilder appendCodePoint(int cp): ajoute un point de code, le convertit en une ou deux unités de code, et retourne la chaîne de caractères résultante.

void setCharAt(int i, char c): règle la ième unité de code à c.
.

StringBuilder insert(int offset, String str): insère une chaîne de caractères à la position offset et renvoie la chaîne de caractères résultante.

StringBuilder insert(int offset, char c): insère une unité de code sur la position offset et renvoie la chaîne de caractères résultante.

StringBuilder delete(int startIndex, int endIndex): efface les unités de code à partir de l’indice startIndex jusqu’à endIndex – 1 et renvoie la chaîne résultante.

String toString(): retourne une chaîne de caractères avec les mêmes données que le contenu du constructeur ou du tampon.

LAISSER UN COMMENTAIRE

Please enter your comment!
Please enter your name here