Java Language
Cordes
Recherche…
Introduction
Les chaînes ( java.lang.String
) sont des morceaux de texte stockés dans votre programme. Les chaînes ne sont pas un type de données primitif en Java , mais elles sont très courantes dans les programmes Java.
En Java, les chaînes sont immuables, ce qui signifie qu'elles ne peuvent pas être modifiées. (Cliquez ici pour une explication plus approfondie de l'immuabilité.)
Remarques
Les chaînes Java étant immuables , toutes les méthodes qui manipulent une String
renvoient un nouvel objet String
. Ils ne changent pas la String
origine. Cela inclut les méthodes de sous-chaîne et de remplacement que les programmeurs C et C ++ pourraient modifier l'objet String
cible.
Utilisez StringBuilder
au lieu de String
si vous souhaitez concaténer plus de deux objets String
dont les valeurs ne peuvent pas être déterminées au moment de la compilation. Cette technique est plus performante que la création de nouveaux objets String
et leur concaténation, car StringBuilder
est mutable.
StringBuffer
peut également être utilisé pour concaténer des objets String
. Cependant, cette classe est moins performante car elle est conçue pour être thread-safe et acquiert un mutex avant chaque opération. Comme vous n'avez presque jamais besoin de sécurité des threads lors de la concaténation de chaînes, il est préférable d'utiliser StringBuilder
.
Si vous pouvez exprimer une concaténation de chaîne en tant qu'expression unique, il est préférable d'utiliser l'opérateur +
. Le compilateur Java convertira une expression contenant +
concaténations en une séquence efficace d’opérations à l’aide de String.concat(...)
ou StringBuilder
. Le conseil d'utilisation de StringBuilder
ne s'applique explicitement que lorsque la concaténation implique plusieurs expressions.
Ne stockez pas d'informations sensibles dans des chaînes. Si quelqu'un est capable d'obtenir un vidage de mémoire de votre application en cours d'exécution, il pourra alors trouver tous les objets String
existants et lire leur contenu. Cela inclut les objets String
inaccessibles et en attente de récupération de place. Si cela pose un problème, vous devrez effacer les données de chaîne sensibles dès que vous en avez terminé. Vous ne pouvez pas faire cela avec des objets String
car ils sont immuables. Par conséquent, il est conseillé d'utiliser des objets char[]
pour stocker des données de caractères sensibles et de les effacer (par exemple, les remplacer par des '\000'
caractères) lorsque vous avez terminé.
Toutes les instances de String
sont créées sur le tas, même les instances qui correspondent aux littéraux de chaîne. La particularité des littéraux de chaîne est que la machine virtuelle Java garantit que tous les littéraux égaux (c'est-à-dire constitués des mêmes caractères) sont représentés par un seul objet String
(ce comportement est spécifié dans JLS). Ceci est implémenté par les chargeurs de classes JVM. Lorsqu'un chargeur de classe charge une classe, il recherche les littéraux de chaîne utilisés dans la définition de classe, chaque fois qu'il en voit un, il vérifie s'il existe déjà un enregistrement dans le pool de chaînes pour ce littéral (en utilisant le littéral comme clé). . S'il existe déjà une entrée pour le littéral, la référence à une instance String
stockée en tant que paire pour ce littéral est utilisée. Sinon, une nouvelle instance String
est créée et une référence à l'instance est stockée pour le littéral (utilisé comme clé) dans le pool de chaînes. (Voir aussi l' internat de chaînes ).
Le pool de chaînes est contenu dans le segment de mémoire Java et est soumis à une récupération de place normale.
Dans les versions de Java antérieures à Java 7, le pool de chaînes était contenu dans une partie spéciale du tas appelée "PermGen". Cette partie n'a été collectée qu'occasionnellement.
Dans Java 7, le pool de chaînes a été retiré de "PermGen".
Notez que les littéraux de chaîne sont implicitement accessibles depuis n'importe quelle méthode qui les utilise. Cela signifie que les objets String
correspondants ne peuvent être récupérés que si le code lui-même est récupéré.
Jusqu'à Java 8, les objets String
sont implémentés sous la forme d'un tableau de caractères UTF-16 (2 octets par caractère). Il existe une proposition dans Java 9 d'implémenter String
comme un tableau d'octets avec un champ d'indicateur de codage à noter si la chaîne est codée sous forme d'octets (LATIN-1) ou de caractères (UTF-16).
Comparaison de chaînes
Afin de comparer les chaînes pour l'égalité, vous devez utiliser les méthodes equals
ou equalsIgnoreCase
l'objet String.
Par exemple, l'extrait suivant déterminera si les deux instances de String
sont égales sur tous les caractères:
String firstString = "Test123";
String secondString = "Test" + 123;
if (firstString.equals(secondString)) {
// Both Strings have the same content.
}
Cet exemple les comparera, indépendamment de leur cas:
String firstString = "Test123";
String secondString = "TEST123";
if (firstString.equalsIgnoreCase(secondString)) {
// Both Strings are equal, ignoring the case of the individual characters.
}
Notez que equalsIgnoreCase
ne vous permet pas de spécifier une Locale
. Par exemple, si vous comparez les deux mots "Taki"
et "TAKI"
en anglais, ils sont égaux; Cependant, ils sont différents en turc (en turc, le minuscule I
est ı
). Pour les cas comme celui - ci, les deux chaînes de conversion en minuscules (ou majuscules) avec des Locale
, puis en comparant avec equals
est la solution.
String firstString = "Taki";
String secondString = "TAKI";
System.out.println(firstString.equalsIgnoreCase(secondString)); //prints true
Locale locale = Locale.forLanguageTag("tr-TR");
System.out.println(firstString.toLowerCase(locale).equals(
secondString.toLowerCase(locale))); //prints false
N'utilisez pas l'opérateur == pour comparer des chaînes
Sauf si vous pouvez garantir que toutes les chaînes ont été internées (voir ci-dessous), vous ne devez pas utiliser les opérateurs ==
ou !=
Pour comparer des chaînes. Ces opérateurs testent en fait des références, et comme plusieurs objets String
peuvent représenter la même chaîne, cela risque de donner une mauvaise réponse.
Utilisez String.equals(Object)
la String.equals(Object)
, qui comparera les objets String en fonction de leurs valeurs. Pour une explication détaillée, veuillez vous référer à Pitfall: utiliser == pour comparer des chaînes .
Comparaison de chaînes dans une déclaration de commutateur
À partir de Java 1.7, il est possible de comparer une variable String à des littéraux dans une instruction switch
. Assurez-vous que la chaîne n'est pas nulle, sinon elle lancera toujours une NullPointerException
. Les valeurs sont comparées à l'aide de String.equals
, c'est-à-dire, sensibles à la casse.
String stringToSwitch = "A";
switch (stringToSwitch) {
case "a":
System.out.println("a");
break;
case "A":
System.out.println("A"); //the code goes here
break;
case "B":
System.out.println("B");
break;
default:
break;
}
Comparaison de chaînes avec des valeurs constantes
Lorsque vous comparez une String
à une valeur constante, vous pouvez placer la valeur constante sur le côté gauche des valeurs equals
pour vous assurer de ne pas obtenir d'exception NullPointerException
si l'autre chaîne est null
.
"baz".equals(foo)
Alors que foo.equals("baz")
lancera une NullPointerException
si foo
est null
, "baz".equals(foo)
sera évalué à false
.
Une alternative plus lisible consiste à utiliser Objects.equals()
, qui effectue une vérification null sur les deux paramètres: Objects.equals(foo, "baz")
.
( Remarque: il est discutable de savoir s'il vaut mieux éviter les NullPointerExceptions
en général, ou les laisser se produire, puis corriger la cause première; voir ici et ici . L'appel à la stratégie d'évitement n'est pas justifiable.)
Classement des chaînes
La classe String
implémente Comparable<String>
avec la méthode String.compareTo
(comme décrit au début de cet exemple). Cela rend l'ordre naturel des objets String
ordre sensible à la casse. La classe String
fournit une constante Comparator<String>
appelée CASE_INSENSITIVE_ORDER
adaptée au tri non sensible à la casse.
Comparaison avec des chaînes internes
La spécification de langage Java ( JLS 3.10.6 ) indique ce qui suit:
"De plus, un littéral de chaîne fait toujours référence à la même instance de la classe
String
. En effet, les littéraux de chaîne - ou plus généralement les chaînes d’expressions constantes - sont internés afin de partager des instances uniques, en utilisant la méthodeString.intern
. "
Cela signifie qu'il est prudent de comparer des références à deux littéraux de chaîne utilisant ==
. De plus, il en va de même pour les références aux objets String
produits à l'aide de la méthode String.intern()
.
Par exemple:
String strObj = new String("Hello!");
String str = "Hello!";
// The two string references point two strings that are equal
if (strObj.equals(str)) {
System.out.println("The strings are equal");
}
// The two string references do not point to the same object
if (strObj != str) {
System.out.println("The strings are not the same object");
}
// If we intern a string that is equal to a given literal, the result is
// a string that has the same reference as the literal.
String internedStr = strObj.intern();
if (internedStr == str) {
System.out.println("The interned string and the literal are the same object");
}
Dans les coulisses, le mécanisme d'internement maintient une table de hachage qui contient toutes les chaînes internes encore accessibles . Lorsque vous appelez intern()
sur une String
, la méthode recherche l'objet dans la table de hachage:
- Si la chaîne est trouvée, cette valeur est renvoyée sous la forme de la chaîne interne.
- Sinon, une copie de la chaîne est ajoutée à la table de hachage et cette chaîne est renvoyée en tant que chaîne interne.
Il est possible d'utiliser l'internement pour permettre de comparer des chaînes en utilisant ==
. Cependant, cela pose des problèmes importants. voir Pitfall - Interner des chaînes pour pouvoir utiliser == est une mauvaise idée pour les détails. Ce n'est pas recommandé dans la plupart des cas.
Changer la casse des caractères dans une chaîne
Le type String
fournit deux méthodes pour convertir des chaînes entre majuscules et minuscules:
-
toUpperCase
pour convertir tous les caractères en majuscules -
toLowerCase
pour convertir tous les caractères en minuscules
Ces méthodes renvoient toutes les deux les chaînes converties en tant que nouvelles instances String
: les objets String
origine ne sont pas modifiés car String
est immuable dans Java. Voir cela pour plus sur l'immutabilité: Immuabilité des chaînes en Java
String string = "This is a Random String";
String upper = string.toUpperCase();
String lower = string.toLowerCase();
System.out.println(string); // prints "This is a Random String"
System.out.println(lower); // prints "this is a random string"
System.out.println(upper); // prints "THIS IS A RANDOM STRING"
Les caractères non alphabétiques, tels que les chiffres et les signes de ponctuation, ne sont pas affectés par ces méthodes. Notez que ces méthodes peuvent également traiter de manière incorrecte certains caractères Unicode sous certaines conditions.
Remarque : Ces méthodes sont sensibles aux paramètres régionaux et peuvent produire des résultats inattendus si elles sont utilisées sur des chaînes destinées à être interprétées indépendamment des paramètres régionaux. Des exemples sont les identificateurs de langage de programmation, les clés de protocole et HTML
balises HTML
.
Par exemple, "TITLE".toLowerCase()
dans une locale turque retourne " tıtle
", où ı (\u0131)
est le caractère LATIN SMALL LETTER DOTLESS I. Pour obtenir des résultats corrects pour les chaînes insensibles aux paramètres régionaux, transmettez Locale.ROOT
tant que paramètre à la méthode de conversion de casse correspondante (par exemple, toLowerCase(Locale.ROOT)
ou toUpperCase(Locale.ROOT)
).
Bien que l'utilisation de Locale.ENGLISH
soit également correcte dans la plupart des cas, la méthode invariante de la langue est Locale.ROOT
.
Une liste détaillée des caractères Unicode nécessitant un boîtier spécial est disponible sur le site Web du Consortium Unicode .
Modification de la casse d'un caractère spécifique dans une chaîne ASCII:
Pour modifier la casse d'un caractère spécifique d'une chaîne ASCII, l'algorithme suivant peut être utilisé:
Pas:
- Déclarez une chaîne.
- Entrez la chaîne.
- Convertissez la chaîne en un tableau de caractères.
- Entrez le caractère à rechercher.
- Recherchez le caractère dans le tableau de caractères.
- Si trouvé, vérifiez si le caractère est en minuscule ou en majuscule.
- Si majuscule, ajoutez 32 au code ASCII du caractère.
- Si en minuscule, soustrayez 32 du code ASCII du caractère.
- Modifiez le caractère d'origine du tableau Caractère.
- Convertissez le tableau de caractères dans la chaîne.
Voila, la caisse du personnage est changée.
Un exemple de code pour l'algorithme est:
Scanner scanner = new Scanner(System.in);
System.out.println("Enter the String");
String s = scanner.next();
char[] a = s.toCharArray();
System.out.println("Enter the character you are looking for");
System.out.println(s);
String c = scanner.next();
char d = c.charAt(0);
for (int i = 0; i <= s.length(); i++) {
if (a[i] == d) {
if (d >= 'a' && d <= 'z') {
d -= 32;
} else if (d >= 'A' && d <= 'Z') {
d += 32;
}
a[i] = d;
break;
}
}
s = String.valueOf(a);
System.out.println(s);
Recherche d'une chaîne dans une autre chaîne
Pour vérifier si une chaîne particulière a
est contenue dans une chaîne b
ou non, nous pouvons utiliser la méthode String.contains()
avec la syntaxe suivante:
b.contains(a); // Return true if a is contained in b, false otherwise
La méthode String.contains()
peut être utilisée pour vérifier si une CharSequence
peut être trouvée dans la chaîne. La méthode recherche la chaîne a
dans la chaîne b
de manière sensible à la casse.
String str1 = "Hello World";
String str2 = "Hello";
String str3 = "helLO";
System.out.println(str1.contains(str2)); //prints true
System.out.println(str1.contains(str3)); //prints false
Pour rechercher la position exacte où une chaîne commence dans une autre chaîne, utilisez String.indexOf()
:
String s = "this is a long sentence";
int i = s.indexOf('i'); // the first 'i' in String is at index 2
int j = s.indexOf("long"); // the index of the first occurrence of "long" in s is 10
int k = s.indexOf('z'); // k is -1 because 'z' was not found in String s
int h = s.indexOf("LoNg"); // h is -1 because "LoNg" was not found in String s
Démonstration en direct sur Ideone
Le String.indexOf()
méthode renvoie le premier indice d'une char
ou String
dans une autre String
. La méthode renvoie -1
si elle n'est pas trouvée.
Remarque : La méthode String.indexOf()
est sensible à la casse.
Exemple de recherche en ignorant la casse:
String str1 = "Hello World";
String str2 = "wOr";
str1.indexOf(str2); // -1
str1.toLowerCase().contains(str2.toLowerCase()); // true
str1.toLowerCase().indexOf(str2.toLowerCase()); // 6
Obtenir la longueur d'une chaîne
Pour obtenir la longueur d'un objet String
, appelez la méthode length()
. La longueur est égale au nombre d'unités de code UTF-16 (caractères) dans la chaîne.
String str = "Hello, World!";
System.out.println(str.length()); // Prints out 13
Une char
dans une chaîne est la valeur UTF-16. Les points de code Unicode dont les valeurs sont ≥ 0x1000 (par exemple, la plupart des émoticônes) utilisent deux positions de caractère. Pour compter le nombre de points de code Unicode dans une chaîne, que chaque point de code correspond à une UTF-16 char
valeur, vous pouvez utiliser la codePointCount
méthode:
int length = str.codePointCount(0, str.length());
Vous pouvez également utiliser un flux de points de code, à partir de Java 8:
int length = str.codePoints().count();
Sous-supports
String s = "this is an example";
String a = s.substring(11); // a will hold the string starting at character 11 until the end ("example")
String b = s.substring(5, 10); // b will hold the string starting at character 5 and ending right before character 10 ("is an")
String b = s.substring(5, b.length()-3); // b will hold the string starting at character 5 ending right before b' s lenght is out of 3 ("is an exam")
Les sous-chaînes peuvent également être appliquées pour trancher et ajouter / remplacer un caractère dans sa chaîne d'origine. Par exemple, vous avez fait face à une date chinoise contenant des caractères chinois, mais vous souhaitez la stocker en tant que chaîne de format au format bien.
String datestring = "2015年11月17日"
datestring = datestring.substring(0, 4) + "-" + datestring.substring(5,7) + "-" + datestring.substring(8,10);
//Result will be 2015-11-17
La méthode de sous-chaîne extrait un morceau d'une String
. Lorsqu'il est fourni un paramètre, le paramètre est le début et le morceau s'étend jusqu'à la fin de la String
. Lorsque deux paramètres sont donnés, le premier paramètre est le caractère de départ et le second paramètre est l'index du caractère immédiatement après la fin (le caractère à l'index n'est pas inclus). Un moyen simple de vérifier est la soustraction du premier paramètre de la seconde qui doit donner la longueur attendue de la chaîne.
Dans les versions JDK <7u6, la méthode de substring
- substring
instancie une String
qui partage le même caractère de sauvegarde char[]
que la String
origine et dont les champs offset
et count
internes sont définis au début et à la longueur du résultat. Un tel partage peut provoquer des fuites de mémoire, ce qui peut être évité en appelant new String(s.substring(...))
pour forcer la création d'une copie, après quoi le char[]
peut être récupéré.
De la 7u6 JDK substring
méthode copie toujours l'ensemble sous-jacent char[]
tableau, ce qui rend le linéaire de la complexité par rapport à une constante précédente , mais qui garantit l'absence de fuites de mémoire en même temps.
Obtenir le nième personnage dans une chaîne
String str = "My String";
System.out.println(str.charAt(0)); // "M"
System.out.println(str.charAt(1)); // "y"
System.out.println(str.charAt(2)); // " "
System.out.println(str.charAt(str.length-1)); // Last character "g"
Pour obtenir le nième caractère d'une chaîne, appelez simplement charAt(n)
sur une String
, où n
est l'index du caractère que vous souhaitez récupérer.
NOTE: l' indice n
commence à 0
, donc le premier élément est à n = 0.
Séparateur de lignes indépendant de la plate-forme
Étant donné que le nouveau séparateur de ligne varie d'une plate-forme à l'autre (par exemple, \n
sur les systèmes de type Unix ou \r\n
sous Windows), il est souvent nécessaire d'avoir un moyen indépendant d'accéder à la plate-forme. En Java, il peut être extrait d'une propriété système:
System.getProperty("line.separator")
Comme le nouveau séparateur de ligne est si souvent nécessaire, à partir de Java 7, une méthode de raccourci renvoyant exactement le même résultat que le code ci-dessus est disponible:
System.lineSeparator()
Remarque : Comme il est très improbable que le nouveau séparateur de ligne change pendant l'exécution du programme, il est préférable de le stocker dans une variable finale statique au lieu de la récupérer à chaque fois que cela est nécessaire.
Lorsque vous utilisez String.format
, utilisez %n
plutôt que \n
ou '\ r \ n' pour générer un nouveau séparateur de ligne indépendant de la plate-forme.
System.out.println(String.format('line 1: %s.%nline 2: %s%n', lines[0],lines[1]));
Ajout de la méthode toString () pour les objets personnalisés
Supposons que vous ayez défini la classe Person
suivante:
public class Person {
String name;
int age;
public Person (int age, String name) {
this.age = age;
this.name = name;
}
}
Si vous instanciez un nouvel objet Person
:
Person person = new Person(25, "John");
et plus tard dans votre code, vous utilisez l'instruction suivante pour imprimer l'objet:
System.out.println(person.toString());
vous obtiendrez une sortie similaire à la suivante:
Person@7ab89d
Ceci est le résultat de l'implémentation de la toString()
définie dans la classe Object
, une super-classe de Person
. La documentation de Object.toString()
indique:
La méthode toString de la classe Object renvoie une chaîne composée du nom de la classe dont l'objet est une instance, du caractère "@" et de la représentation hexadécimale non signée du code de hachage de l'objet. En d'autres termes, cette méthode renvoie une chaîne égale à la valeur de:
getClass().getName() + '@' + Integer.toHexString(hashCode())
Donc, pour une sortie significative, vous devrez remplacer la toString()
:
@Override
public String toString() {
return "My name is " + this.name + " and my age is " + this.age;
}
Maintenant, le résultat sera:
My name is John and my age is 25
Vous pouvez aussi écrire
System.out.println(person);
En fait, println()
invoque implicitement la méthode toString
sur l'objet.
Fendre les cordes
Vous pouvez fractionner une String
sur un caractère de délimitation particulier ou une expression régulière , vous pouvez utiliser la méthode String.split()
avec la signature suivante:
public String[] split(String regex)
Notez que le caractère de délimitation ou l'expression régulière sont supprimés du tableau de chaînes résultant.
Exemple utilisant un caractère de délimitation:
String lineFromCsvFile = "Mickey;Bolton;12345;121216";
String[] dataCells = lineFromCsvFile.split(";");
// Result is dataCells = { "Mickey", "Bolton", "12345", "121216"};
Exemple utilisant une expression régulière:
String lineFromInput = "What do you need from me?";
String[] words = lineFromInput.split("\\s+"); // one or more space chars
// Result is words = {"What", "do", "you", "need", "from", "me?"};
Vous pouvez même séparer directement un littéral String
:
String[] firstNames = "Mickey, Frank, Alicia, Tom".split(", ");
// Result is firstNames = {"Mickey", "Frank", "Alicia", "Tom"};
Attention : n'oubliez pas que le paramètre est toujours traité comme une expression régulière.
"aaa.bbb".split("."); // This returns an empty array
Dans l'exemple précédent .
est traité comme le caractère générique d'expression régulière qui correspond à n'importe quel caractère, et comme chaque caractère est un délimiteur, le résultat est un tableau vide.
Fractionnement basé sur un délimiteur qui est un méta-caractère regex
Les caractères suivants sont considérés comme spéciaux (aka méta-caractères) dans regex
< > - = ! ( ) [ ] { } \ ^ $ | ? * + .
Pour diviser une chaîne en fonction de l'un des délimiteurs ci-dessus, vous devez soit y échapper en utilisant \\
soit utiliser Pattern.quote()
:
En utilisant
Pattern.quote()
:String s = "a|b|c"; String regex = Pattern.quote("|"); String[] arr = s.split(regex);
Fuyant les caractères spéciaux:
String s = "a|b|c"; String[] arr = s.split("\\|");
Split supprime les valeurs vides
split(delimiter)
supprime par défaut les chaînes vides du tableau de résultats. Pour désactiver ce mécanisme, nous devons utiliser une version surchargée de split(delimiter, limit)
avec une limite définie sur une valeur négative telle que
String[] split = data.split("\\|", -1);
split(regex)
renvoie en interne le résultat du split(regex, 0)
.
Le paramètre limit contrôle le nombre de fois où le motif est appliqué et affecte donc la longueur du tableau résultant.
Si la limite n est supérieure à zéro, alors le motif sera appliqué au maximum n - 1 fois, la longueur du tableau ne sera pas supérieure à n et la dernière entrée du tableau contiendra toutes les entrées au-delà du dernier délimiteur correspondant.
Si n est négatif, le motif sera appliqué autant de fois que possible et le tableau pourra avoir n'importe quelle longueur.
Si n est égal à zéro, le modèle sera appliqué autant de fois que possible, le tableau peut avoir n'importe quelle longueur et les chaînes vides à la fin seront supprimées.
Fractionnement avec un StringTokenizer
Outre la méthode split()
, les chaînes peuvent également être divisées en utilisant un StringTokenizer
.
StringTokenizer
est encore plus restrictif que String.split()
, et un peu plus difficile à utiliser. Il est essentiellement conçu pour extraire des jetons délimités par un ensemble fixe de caractères (donnés sous forme de String
). Chaque personnage agira comme un séparateur. A cause de cette restriction, il est environ deux fois plus rapide que String.split()
.
Les jeux de caractères par défaut sont des espaces vides ( \t\n\r\f
). L'exemple suivant imprimera chaque mot séparément.
String str = "the lazy fox jumped over the brown fence";
StringTokenizer tokenizer = new StringTokenizer(str);
while (tokenizer.hasMoreTokens()) {
System.out.println(tokenizer.nextToken());
}
Cela va imprimer:
the
lazy
fox
jumped
over
the
brown
fence
Vous pouvez utiliser différents jeux de caractères pour la séparation.
String str = "jumped over";
// In this case character `u` and `e` will be used as delimiters
StringTokenizer tokenizer = new StringTokenizer(str, "ue");
while (tokenizer.hasMoreTokens()) {
System.out.println(tokenizer.nextToken());
}
Cela va imprimer:
j
mp
d ov
r
Joindre des chaînes avec un délimiteur
Un tableau de chaînes peut être joint en utilisant la méthode statique String.join()
:
String[] elements = { "foo", "bar", "foobar" };
String singleString = String.join(" + ", elements);
System.out.println(singleString); // Prints "foo + bar + foobar"
De même, il existe une méthode String.join()
surchargée pour les Iterable
s.
Pour avoir un contrôle précis sur la jointure, vous pouvez utiliser la classe StringJoiner :
StringJoiner sj = new StringJoiner(", ", "[", "]");
// The last two arguments are optional,
// they define prefix and suffix for the result string
sj.add("foo");
sj.add("bar");
sj.add("foobar");
System.out.println(sj); // Prints "[foo, bar, foobar]"
Pour joindre un flux de chaînes, vous pouvez utiliser le collecteur de jointure :
Stream<String> stringStream = Stream.of("foo", "bar", "foobar");
String joined = stringStream.collect(Collectors.joining(", "));
System.out.println(joined); // Prints "foo, bar, foobar"
Il y a une option pour définir le préfixe et le suffixe ici aussi:
Stream<String> stringStream = Stream.of("foo", "bar", "foobar");
String joined = stringStream.collect(Collectors.joining(", ", "{", "}"));
System.out.println(joined); // Prints "{foo, bar, foobar}"
Cordes d'inversion
Il y a plusieurs manières d'inverser une chaîne pour la faire reculer.
StringBuilder / StringBuffer:
String code = "code"; System.out.println(code); StringBuilder sb = new StringBuilder(code); code = sb.reverse().toString(); System.out.println(code);
Tableau de caractères:
String code = "code"; System.out.println(code); char[] array = code.toCharArray(); for (int index = 0, mirroredIndex = array.length - 1; index < mirroredIndex; index++, mirroredIndex--) { char temp = array[index]; array[index] = array[mirroredIndex]; array[mirroredIndex] = temp; } // print reversed System.out.println(new String(array));
Compter les occurrences d'une sous-chaîne ou d'un caractère dans une chaîne
countMatches
méthode countMatches
d' org.apache.commons.lang3.StringUtils est généralement utilisée pour compter les occurrences d'une sous-chaîne ou d'un caractère dans une String
:
import org.apache.commons.lang3.StringUtils;
String text = "One fish, two fish, red fish, blue fish";
// count occurrences of a substring
String stringTarget = "fish";
int stringOccurrences = StringUtils.countMatches(text, stringTarget); // 4
// count occurrences of a char
char charTarget = ',';
int charOccurrences = StringUtils.countMatches(text, charTarget); // 3
Sinon, pour faire la même chose avec les API Java standard, vous pouvez utiliser des expressions régulières:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
String text = "One fish, two fish, red fish, blue fish";
System.out.println(countStringInString("fish", text)); // prints 4
System.out.println(countStringInString(",", text)); // prints 3
public static int countStringInString(String search, String text) {
Pattern pattern = Pattern.compile(search);
Matcher matcher = pattern.matcher(text);
int stringOccurrences = 0;
while (matcher.find()) {
stringOccurrences++;
}
return stringOccurrences;
}
Concaténation de chaînes et StringBuilders
La concaténation de chaînes peut être effectuée à l'aide de l'opérateur +
. Par exemple:
String s1 = "a";
String s2 = "b";
String s3 = "c";
String s = s1 + s2 + s3; // abc
Normalement, une implémentation du compilateur effectuera la concaténation ci-dessus en utilisant des méthodes impliquant un StringBuilder
sous le capot. Une fois compilé, le code ressemblerait à celui ci-dessous:
StringBuilder sb = new StringBuilder("a");
String s = sb.append("b").append("c").toString();
StringBuilder
dispose de plusieurs méthodes surchargées pour ajouter différents types, par exemple, pour ajouter un int
au lieu d'une String
. Par exemple, une implémentation peut convertir:
String s1 = "a";
String s2 = "b";
String s = s1 + s2 + 2; // ab2
à ce qui suit:
StringBuilder sb = new StringBuilder("a");
String s = sb.append("b").append(2).toString();
Les exemples ci-dessus illustrent une opération de concaténation simple effectuée efficacement à un seul endroit du code. La concaténation implique une seule instance de StringBuilder
. Dans certains cas, une concaténation est effectuée de manière cumulative, par exemple dans une boucle:
String result = "";
for(int i = 0; i < array.length; i++) {
result += extractElement(array[i]);
}
return result;
Dans de tels cas, l'optimisation du compilateur n'est généralement pas appliquée et chaque itération crée un nouvel objet StringBuilder
. Cela peut être optimisé en transformant explicitement le code pour utiliser un seul StringBuilder
:
StringBuilder result = new StringBuilder();
for(int i = 0; i < array.length; i++) {
result.append(extractElement(array[i]));
}
return result.toString();
Un StringBuilder
sera initialisé avec un espace vide de 16 caractères seulement. Si vous savez à l'avance que vous allez créer des chaînes plus grandes, il peut être utile de l'initialiser suffisamment à l'avance pour que le tampon interne n'ait pas besoin d'être redimensionné:
StringBuilder buf = new StringBuilder(30); // Default is 16 characters
buf.append("0123456789");
buf.append("0123456789"); // Would cause a reallocation of the internal buffer otherwise
String result = buf.toString(); // Produces a 20-chars copy of the string
Si vous produisez de nombreuses chaînes, il est conseillé de réutiliser StringBuilder
:
StringBuilder buf = new StringBuilder(100);
for (int i = 0; i < 100; i++) {
buf.setLength(0); // Empty buffer
buf.append("This is line ").append(i).append('\n');
outputfile.write(buf.toString());
}
Si (et seulement si) plusieurs threads écrivent dans le même tampon, utilisez StringBuffer , qui est une version synchronized
de StringBuilder
. Mais comme un seul thread écrit généralement dans un tampon, il est généralement plus rapide d'utiliser StringBuilder
sans synchronisation.
Utilisation de la méthode concat ():
String string1 = "Hello ";
String string2 = "world";
String string3 = string1.concat(string2); // "Hello world"
Cela retourne une nouvelle chaîne qui est string1 avec string2 ajouté à la fin. Vous pouvez également utiliser la méthode concat () avec des littéraux de chaîne, comme dans:
"My name is ".concat("Buyya");
Remplacement de pièces de chaînes
Deux manières de remplacer: par regex ou par correspondance exacte.
Remarque: l'objet String d'origine sera inchangé, la valeur de retour contient la chaîne modifiée.
Correspondance exacte
Remplacez un seul caractère par un autre caractère unique:
String replace(char oldChar, char newChar)
Renvoie une nouvelle chaîne résultant du remplacement de toutes les occurrences de oldChar dans cette chaîne par newChar.
String s = "popcorn";
System.out.println(s.replace('p','W'));
Résultat:
WoWcorn
Remplacez la séquence de caractères par une autre séquence de caractères:
String replace(CharSequence target, CharSequence replacement)
Remplace chaque sous-chaîne de cette chaîne qui correspond à la séquence cible littérale par la séquence de remplacement littérale spécifiée.
String s = "metal petal et al.";
System.out.println(s.replace("etal","etallica"));
Résultat:
metallica petallica et al.
Regex
Remarque : le regroupement utilise le caractère $
pour référencer les groupes, par exemple $1
.
Remplacer toutes les correspondances:
String replaceAll(String regex, String replacement)
Remplace chaque sous-chaîne de cette chaîne qui correspond à l'expression régulière donnée avec le remplacement donné.
String s = "spiral metal petal et al.";
System.out.println(s.replaceAll("(\\w*etal)","$1lica"));
Résultat:
spiral metallica petallica et al.
Remplacez le premier match uniquement:
String replaceFirst(String regex, String replacement)
Remplace la première sous-chaîne de cette chaîne qui correspond à l'expression régulière donnée avec le remplacement donné
String s = "spiral metal petal et al.";
System.out.println(s.replaceAll("(\\w*etal)","$1lica"));
Résultat:
spiral metallica petal et al.
Supprimer les espaces au début et à la fin d'une chaîne
La méthode trim()
renvoie une nouvelle chaîne avec les espaces blancs de début et de fin supprimés.
String s = new String(" Hello World!! ");
String t = s.trim(); // t = "Hello World!!"
Si vous trim
une chaîne qui n'a pas d'espace à supprimer, vous recevrez la même instance String.
Notez que la méthode trim()
a sa propre notion d’espace , qui diffère de la notion utilisée par la méthode Character.isWhitespace()
:
Tous les caractères de contrôle ASCII avec les codes
U+0000
àU+0020
sont considérés comme des espaces et sont supprimés partrim()
. Cela inclutU+0020 'SPACE'
,U+0009 'CHARACTER TABULATION'
,U+000A 'LINE FEED'
etU+000D 'CARRIAGE RETURN'
, mais aussi les caractères commeU+0007 'BELL'
.Les espaces blancs Unicode tels que
U+00A0 'NO-BREAK SPACE'
ouU+2003 'EM SPACE'
ne sont pas reconnus partrim()
.
Stockage de pool de chaînes et de tas
Comme beaucoup d'objets Java, toutes les instances de String
sont créées sur le tas, même les littéraux. Lorsque la machine JVM trouve un littéral String
qui n'a pas de référence équivalente dans le tas, la machine virtuelle Java crée une instance String
correspondante sur le segment de mémoire et stocke également une référence à l'instance String
nouvellement créée dans le pool String. Toute autre référence au même littéral String
est remplacée par l'instance String
précédemment créée dans le tas.
Regardons l'exemple suivant:
class Strings
{
public static void main (String[] args)
{
String a = "alpha";
String b = "alpha";
String c = new String("alpha");
//All three strings are equivalent
System.out.println(a.equals(b) && b.equals(c));
//Although only a and b reference the same heap object
System.out.println(a == b);
System.out.println(a != c);
System.out.println(b != c);
}
}
Le résultat de ce qui précède est:
true
true
true
true
Lorsque nous utilisons des guillemets doubles pour créer une chaîne, celle-ci recherche d'abord la chaîne avec la même valeur dans le pool de chaînes. Si elle est trouvée, elle renvoie simplement la référence, sinon elle crée une nouvelle chaîne dans le pool, puis renvoie la référence.
Cependant, en utilisant un nouvel opérateur, nous forçons la classe String à créer un nouvel objet String dans l’espace du tas. Nous pouvons utiliser la méthode intern () pour la placer dans le pool ou faire référence à un autre objet String d'un pool de chaînes ayant la même valeur.
Le pool de chaînes lui-même est également créé sur le tas.
Avant Java 7, les littéraux de String
étaient stockés dans le pool de constante d'exécution dans la zone de méthode de PermGen
, qui avait une taille fixe.
Le pool de chaînes réside également dans PermGen
.
Dans JDK 7, les chaînes internes ne sont plus allouées dans la génération permanente du segment de mémoire Java, mais sont plutôt allouées dans la partie principale du segment de mémoire Java (appelées générations jeunes et anciennes), avec les autres objets créés par l'application. . Cette modification se traduira par plus de données résidant dans le segment de mémoire principal Java et moins de données dans la génération permanente, ce qui peut nécessiter un ajustement de la taille des segments. La plupart des applications ne verront que des différences relativement faibles dans l'utilisation du tas en raison de ce changement, mais les applications plus volumineuses qui chargent de nombreuses classes ou qui utilisent
String.intern()
méthodeString.intern()
verront des différences plus significatives.
Commutateur insensible à la casse
switch
lui-même ne peut pas être paramétré pour être insensible à la casse, mais s'il est absolument nécessaire, peut se comporter de manière insensible à la chaîne d'entrée en utilisant toLowerCase()
ou toUpperCase
:
switch (myString.toLowerCase()) {
case "case1" :
...
break;
case "case2" :
...
break;
}
Il faut se méfier
-
Locale
peuvent affecter la manière dont les cas changent ! - Il faut prendre soin de ne pas avoir de majuscules dans les étiquettes - celles-ci ne seront jamais exécutées!