JavaRush /Blog Java /Random-FR /Remplacer la chaîne en Java

Remplacer la chaîne en Java

Publié dans le groupe Random-FR
Dans le travail d'un programmeur, certaines tâches ou leurs composants peuvent souvent être répétés. C'est pourquoi je voudrais aujourd'hui aborder un sujet souvent rencontré dans le travail quotidien de tout développeur Java. Remplacer la chaîne en Java - 1Supposons que vous receviez une certaine chaîne d'une certaine méthode. Et tout semble bien, mais il y a une petite chose qui ne vous convient pas. Par exemple, le séparateur ne convient pas et il vous en faut un autre (ou pas du tout). Que peut-on faire dans une telle situation ? Naturellement, utilisez les méthodes replacede la classe String.

Remplacement de la chaîne Java

L'objet type Stringa quatre variantes de la méthode de remplacementreplace :
  • replace(char, char);
  • replace(CharSequence, CharSequence);
  • replaceFirst(String, String);
  • replaceAll(String, String).
Le but de toutes ces méthodes est le même : remplacer une partie d’une chaîne par une autre chaîne. Regardons-les de plus près. 1.replace(char, char) String replace(char oldChar, char newChar) - remplace toutes les occurrences du caractère du premier argument oldCharpar le second - newChar. Dans cet exemple, nous remplacerons la virgule par un point-virgule :
String value = "In JavaRush, Diego the best, Diego is Java God".replace(',', ';');
System.out.println(value);
Sortie de la console :
In JavaRush; Diego the best; Diego is Java God
2.replace(CharSequence, CharSequence) Remplace chaque sous-chaîne d'une chaîne qui correspond à une séquence de caractères spécifiée par une séquence de caractères de remplacement.
String value = "In JavaRush, Diego the best, Diego is Java God".replace("Java", "Rush");
System.out.println(value);
Conclusion:
In RushRush, Diego the best, Diego is Rush God
3.replaceFirst(String, String) String replaceFirst(String regex, String replacement) - Remplace la première sous-chaîne qui correspond à l'expression régulière spécifiée par une chaîne de remplacement. Lorsque vous utilisez une expression régulière non valide, vous pouvez intercepter une PatternSyntaxException (ce qui n'est pas une bonne chose). Dans cet exemple, remplaçons le nom du robot champion :
String value = "In JavaRush, Diego the best, Diego is Java God".replaceFirst("Diego", "Amigo");
System.out.println(value);
Sortie de la console :
In JavaRush, Amigo the best, Diego is Java God
Comme nous pouvons le constater, seule la première entrée de « Diego » a changé, mais les suivantes sont restées laissées de côté, c'est-à-dire intactes. 4. replaceAll()en Java String replaceAll(String regex, String replacement) - cette méthode remplace toutes les occurrences d'une sous-chaîne dans une chaîne regexpar replacement. Une expression régulière peut être utilisée comme premier argument regex. A titre d'exemple, essayons d'effectuer le remplacement précédent par des noms, mais avec une nouvelle méthode :
String value = "In JavaRush, Diego the best, Diego is Java God".replaceAll("Diego", "Amigo");
System.out.println(value);
Sortie de la console :
In JavaRush, Amigo the best, Amigo is Java God
Comme nous pouvons le constater, tous les symboles ont été complètement remplacés par ceux nécessaires. Je pense qu'Amigo sera content =)

Expressions régulières

Il a été dit plus haut qu'il était possible de remplacer à l'aide d'une expression régulière. Tout d’abord, clarifions par nous-mêmes ce qu’est une expression régulière ? Les expressions régulières sont un langage formel permettant de rechercher et de manipuler des sous-chaînes dans un texte, basé sur l'utilisation de métacaractères (caractères génériques). En termes simples, il s'agit d'un modèle de caractères et de métacaractères qui définit une règle de recherche. Par exemple : \D- un modèle décrivant tout caractère non numérique ; \d— définit tout caractère numérique, qui peut également être décrit comme [0-9]; [a-zA-Z]— un modèle décrivant les caractères latins de a à z, insensible à la casse ; Considérons l'application dans une méthode replaceAllde classeString :
String value = "In JavaRush, Diego the best, Diego is Java God".replaceAll("\\s[a-zA-Z]{5}\\s", " Amigo ");
System.out.println(value);
Sortie de la console :
In JavaRush, Amigo the best, Amigo is Java God
\\s[a-zA-Z]{5}\\s— décrit un mot de 5 caractères latins entourés d'espaces. En conséquence, ce modèle est remplacé par la chaîne que nous avons transmise.

Remplacement de l'expression régulière Java

Fondamentalement, pour utiliser des expressions régulières en Java, les capacités du java.util.regex. Les classes clés sont :
  1. Pattern- une classe qui fournit une version compilée d'une expression régulière.
  2. Matcher— cette classe interprète le modèle et détermine les correspondances dans la chaîne qu'elle reçoit.
Généralement, ces deux classes fonctionnent conjointement. Alors, à quoi ressemblera notre objet précédent, mais avec l'aide de Matcheret Pattern:
Pattern pattern = Pattern.compile("\\s[a-zA-Z]{5}\\s");
Matcher matcher = pattern.matcher("In JavaRush, Diego the best, Diego is Java God");
String value = matcher.replaceAll(" Amigo ");
System.out.println(value);
Et notre conclusion sera la même :
In JavaRush, Amigo the best, Amigo is Java God
Vous pouvez en savoir plus sur les expressions régulières dans cet article .

Alternative à replaceAll

Il ne fait aucun doute que les méthodes replacesont Stringtrès impressionnantes, mais on ne peut ignorer le fait qu’il Strings’agit immutabled’un objet, c’est-à-dire qu’il ne peut pas être modifié après sa création. Par conséquent, lorsque nous remplaçons certaines parties d'une chaîne à l'aide de méthodes replace, nous ne modifions pas l'objet String, mais en créons un nouveau à chaque fois, avec le contenu nécessaire. Mais il faut beaucoup de temps pour créer un nouvel objet à chaque fois, n'est-ce pas ? Surtout quand il ne s'agit pas de quelques objets, mais de quelques centaines, voire milliers. Bon gré mal gré, vous commencez à réfléchir à des alternatives. Et quelles alternatives avons-nous ? Remplacer la chaîne en Java - 2Hmm... Quand il s'agit de Stringsa propriété immutable, vous pensez immédiatement à des alternatives, mais pas immutable, à savoir StringBuilder/StringBuffer . Comme nous nous en souvenons, ces classes ne diffèrent pas réellement, sauf qu'elles StringBuffersont optimisées pour une utilisation dans un environnement multithread, StringBuilderelles fonctionnent donc un peu plus rapidement en utilisation monothread. Sur cette base, nous utiliserons aujourd'hui StringBuilder. Cette classe a de nombreuses méthodes intéressantes, mais c'est précisément ce qui nous intéresse maintenant replace. StringBuilder replace(int start, int end, String str)— cette méthode remplace les caractères d'une sous-chaîne de cette séquence par des caractères de la chaîne spécifiée. La sous-chaîne commence au début spécifié et continue jusqu'au caractère à la fin de l'index, -1ou jusqu'à la fin de la séquence si aucun caractère de ce type n'existe. Regardons un exemple :
StringBuilder strBuilder = new StringBuilder("Java Rush");
strBuilder.replace(5, 9, "God");
System.out.println(strBuilder);
Conclusion:
Java God
Comme vous pouvez le voir, nous indiquons l'intervalle dans lequel nous voulons écrire la chaîne et écrivons une sous-chaîne au-dessus de ce qui se trouve dans l'intervalle. Ainsi, en utilisant l'aide, StringBuildernous allons recréer un analogue de la méthode replaceall java. À quoi cela ressemblera-t-il :
public static String customReplaceAll(String str, String oldStr, String newStr) {

   if ("".equals(str) || "".equals(oldStr) || oldStr.equals(newStr)) {
       return str;
   }
   if (newStr == null) {
       newStr = "";
   }
   final int strLength = str.length();
   final int oldStrLength = oldStr.length();
   StringBuilder builder = new StringBuilder(str);

   for (int i = 0; i < strLength; i++) {
       int index = builder.indexOf(oldStr, i);

       if (index == -1) {
           if (i == 0) {
               return str;
           }
           return builder.toString();
       }
       builder = builder.replace(index, index + oldStrLength, newStr);

   }
       return builder.toString();
}
Cela fait peur à première vue, mais avec un peu de compréhension on comprend que tout n'est pas si compliqué et assez logique. Nous avons trois arguments :
  • str— une ligne dans laquelle on souhaite remplacer certaines sous-chaînes ;
  • oldStr— représentation des sous-chaînes que nous remplacerons ;
  • newStr- par quoi nous allons le remplacer.
ifNous avons besoin du premier pour vérifier les données entrantes, et si la chaîne strest oldStrvide ou si la nouvelle sous-chaîne newStrest égale à l'ancienne oldStr, alors l'exécution de la méthode n'aura aucun sens. Par conséquent, nous renvoyons la chaîne d'origine - str. Ensuite, nous vérifions newStr, nullet si tel est le cas, nous le convertissons dans un format de chaîne vide qui nous convient mieux - "". Ensuite nous avons la déclaration des variables dont nous avons besoin :
  • longueur totale de la chaînestr ;
  • longueur de la sous-chaîneoldStr ;
  • objet StringBuilderà partir d’une chaîne partagée.
Nous démarrons une boucle qui doit s'exécuter un nombre de fois égal à la longueur de la chaîne totale (mais, très probablement, cela n'arrivera jamais). En utilisant la méthode de classe StringBuilder- indexOf- nous trouvons l'index de la première occurrence de la sous-chaîne qui nous intéresse. Malheureusement, je voudrais noter que cela indexOfne fonctionne pas avec les expressions régulières, donc notre méthode finale ne fonctionnera qu'avec les occurrences de chaînes (( Si cet index est égal à -1, alors il n'y a plus d'occurrences de ces occurrences dans l'objet actuel StringBuilder, nous quittons donc la méthode avec le résultat qui nous intéresse : il est contenu dans notre StringBuilder, que nous convertissons en String, en utilisant toString. Si notre index est égal -1à la première itération de la boucle, alors la sous-chaîne qui doit être remplacée n'était pas dans le général chaîne initialement. Par conséquent, dans une telle situation, nous renvoyons simplement la chaîne générale. Ensuite, nous avons et la méthode décrite ci-dessus est utilisée replacepour StringBuilderutiliser l'index trouvé de l'occurrence pour indiquer les coordonnées de la sous-chaîne à remplacer. Cette boucle s'exécutera autant de fois que de sous-chaînes à remplacer sont trouvées. Si la chaîne est constituée uniquement du caractère à remplacer, alors seulement dans ce cas nous avons La boucle s'exécutera complètement et nous obtiendrons le résultat StringBuilderconverti en chaîne. Nous devons vérifier l’exactitude de cette méthode, n’est-ce pas ? Écrivons un test qui vérifie le fonctionnement de la méthode dans diverses situations :
@Test
public void customReplaceAllTest() {
   String str = "qwertyuiop__qwertyuiop__";

   String firstCase = Solution.customReplaceAll(str, "q", "a");
   String firstResult = "awertyuiop__awertyuiop__";
   assertEquals(firstCase, firstResult);

   String secondCase = Solution.customReplaceAll(str, "q", "ab");
   String secondResult = "abwertyuiop__abwertyuiop__";
   assertEquals(secondCase, secondResult);

   String thirdCase = Solution.customReplaceAll(str, "rtyu", "*");
   String thirdResult = "qwe*iop__qwe*iop__";
   assertEquals(thirdCase, thirdResult);

   String fourthCase = Solution.customReplaceAll(str, "q", "");
   String fourthResult = "wertyuiop__wertyuiop__";
   assertEquals(fourthCase, fourthResult);

   String fifthCase = Solution.customReplaceAll(str, "uio", "");
   String fifthResult = "qwertyp__qwertyp__";
   assertEquals(fifthCase, fifthResult);

   String sixthCase = Solution.customReplaceAll(str, "", "***");
   assertEquals(sixthCase, str);

   String seventhCase = Solution.customReplaceAll("", "q", "***");
   assertEquals(seventhCase, "");
}
Peut être divisé en 7 tests distincts, chacun étant responsable de son propre scénario de test. Après l'avoir lancé, nous verrons qu'il est vert, c'est-à-dire réussi. Eh bien, cela semble être tout. Attendez, nous avons dit plus haut que cette méthode sera beaucoup plus rapide replaceAllque String. Voyons voir:
String str = "qwertyuiop__qwertyuiop__";
long firstStartTime = System.nanoTime();

for (long i = 0; i < 10000000L; i++) {
   str.replaceAll("tyu", "#");
}

double firstPerformance = System.nanoTime() - firstStartTime;

long secondStartTime = System.nanoTime();

for (long i = 0; i < 10000000L; i++) {
   customReplaceAll(str, "tyu", "#");
}

double secondPerformance = System.nanoTime() - secondStartTime;

System.out.println("Performance ratio  - " +  firstPerformance / secondPerformance);
Ensuite, ce code a été exécuté trois fois et nous avons obtenu les résultats suivants : Sortie de la console :
Performance ratio  - 5.012148941181627
 
Performance ratio  - 5.320637176017641
 
Performance ratio  - 4.719192686500394
Comme nous pouvons le constater, en moyenne notre méthode est 5 fois plus productive que le replaceAllcours classique ! StringEh bien, enfin, effectuons le même contrôle, mais, pour ainsi dire, en vain. En d’autres termes, dans le cas où aucune correspondance n’est trouvée. Remplaçons la chaîne de recherche de "tyu"par "--". Trois exécutions ont donné les résultats suivants : Sortie de la console :
Performance ratio  - 8.789647093542246
 
Performance ratio  - 9.177105482660881
 
Performance ratio  - 8.520964375227406
En moyenne, les performances dans les cas où aucune correspondance n'a été trouvée ont été multipliées par 8,8 ! Remplacer la chaîne en Java - 4
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION