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.

Java SE 7

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.

Java SE 7

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.
}

Démo en direct

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.
}

Démo en direct

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

Démo en direct


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

Java SE 7

À 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;
}

Démo en direct

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 .

Java SE 7

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éthode String.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:

  1. Déclarez une chaîne.
  2. Entrez la chaîne.
  3. Convertissez la chaîne en un tableau de caractères.
  4. Entrez le caractère à rechercher.
  5. Recherchez le caractère dans le tableau de caractères.
  6. 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.
  7. Modifiez le caractère d'origine du tableau Caractère.
  8. 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

Démo en direct sur Ideone


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

Démo en direct sur Ideone

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

Démo en direct sur Ideone

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.

Java SE 7

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é.

Java SE 7

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")
Java SE 7

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());

Démo en direct sur Ideone

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);

Démo en direct sur Ideone

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

Java SE 8

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.

  1. StringBuilder / StringBuffer:

     String code = "code";
     System.out.println(code);
    
     StringBuilder sb = new StringBuilder(code); 
     code = sb.reverse().toString();
    
     System.out.println(code);
    
  2. 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 par trim() . Cela inclut U+0020 'SPACE' , U+0009 'CHARACTER TABULATION' , U+000A 'LINE FEED' et U+000D 'CARRIAGE RETURN' , mais aussi les caractères comme U+0007 'BELL' .

  • Les espaces blancs Unicode tels que U+00A0 'NO-BREAK SPACE' ou U+2003 'EM SPACE' ne sont pas reconnus par trim() .

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

Diagramme du pool de tas et de chaînes Java 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.

Java SE 7

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 .

Java SE 7

RFC: 6962931

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éthode String.intern() verront des différences plus significatives.

Commutateur insensible à la casse

Java SE 7

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!


Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow