JavaRush /Java Blog /Random EN /replace string in java

replace string in java

Published in the Random EN group
In a programmer's work, quite often some tasks or their components may be repeated. Therefore, today I would like to touch on a topic that is often encountered in the daily work of any Java developer. Replace string in Java - 1Let's assume that you receive a certain string from a certain method. And everything about it seems to be good, but there is some little thing that doesn’t suit you. For example, the separator is not suitable, and you need some other one (or not at all). What can be done in such a situation? Naturally, use the methods replaceof the class String.

Java string replace

The type object Stringhas four variations of the replacement method replace:
  • replace(char, char);
  • replace(CharSequence, CharSequence);
  • replaceFirst(String, String);
  • replaceAll(String, String).
The purpose of all these methods is the same - replacing part of a string with another string. Let's take a closer look at them. 1.replace(char, char) String replace(char oldChar, char newChar) - replaces all occurrences of the character of the first argument oldCharwith the second - newChar. In this example, we'll replace the comma with a semicolon:
String value = "In JavaRush, Diego the best, Diego is Java God".replace(',', ';');
System.out.println(value);
Console output:
In JavaRush; Diego the best; Diego is Java God
2.replace(CharSequence, CharSequence) Replaces each substring of a string that matches a specified sequence of characters with a sequence of replacement characters.
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) - Replaces the first substring that matches the specified regular expression with a replacement string. When using an invalid regular expression, you can catch a PatternSyntaxException (which is not a good thing). In this example, let's replace the name of the champion robot:
String value = "In JavaRush, Diego the best, Diego is Java God".replaceFirst("Diego", "Amigo");
System.out.println(value);
Console output:
In JavaRush, Amigo the best, Diego is Java God
As we can see, only the first entry of “Diego” has changed, but the subsequent ones remained left out—that is, untouched. 4. replaceAll()in Java String replaceAll(String regex, String replacement) - this method replaces all occurrences of a substring in a string regexwith replacement. A regular expression can be used as the first argument regex. As an example, let's try to perform the previous replacement with names, but with a new method:
String value = "In JavaRush, Diego the best, Diego is Java God".replaceAll("Diego", "Amigo");
System.out.println(value);
Console output:
In JavaRush, Amigo the best, Amigo is Java God
As we can see, all symbols have been completely replaced with the necessary ones. I think Amigo will be pleased =)

Regular Expressions

It was said above that it is possible to replace using a regular expression. First, let's clarify for ourselves what a regular expression is? Regular expressions are a formal language for searching and manipulating substrings in text, based on the use of metacharacters (wildcards). Simply put, it is a pattern of characters and metacharacters that defines a search rule. For example: \D- a template describing any non-digital character; \d— defines any numeric character, which can also be described as [0-9]; [a-zA-Z]— a template describing Latin characters from a to z, case insensitive; Consider the application in a replaceAllclass method String:
String value = "In JavaRush, Diego the best, Diego is Java God".replaceAll("\\s[a-zA-Z]{5}\\s", " Amigo ");
System.out.println(value);
Console output:
In JavaRush, Amigo the best, Amigo is Java God
\\s[a-zA-Z]{5}\\s— describes a word of 5 Latin characters surrounded by spaces. Accordingly, this template is replaced with the string we passed.

Java regex replace

Basically, to use regular expressions in Java, the capabilities of the java.util.regex. The key classes are:
  1. Pattern- a class that provides a compiled version of a regular expression.
  2. Matcher— this class interprets the pattern and determines matches in the string it receives.
Typically, these two classes work in conjunction. So, what will our previous object look like, but with the help of Matcherand 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);
And our conclusion will be the same:
In JavaRush, Amigo the best, Amigo is Java God
You can read more about regular expressions in this article .

Alternative to replaceAll

There is no doubt that the methods replaceare Stringvery impressive, but one cannot ignore the fact that Stringit is immutablean object, that is, it cannot be changed after its creation. Therefore, when we replace some parts of a string using methods replace, we do not change the object String, but create a new one each time, with the necessary contents. But it takes a long time to create a new object every time, doesn’t it? Especially when the question is not a couple of objects, but a couple of hundreds, or even thousands. Willy-nilly, you begin to think about alternatives. And what alternatives do we have? Replace string in Java - 2Hmm... When it comes to Stringits property immutable, you immediately think of alternatives, but not immutable, namely StringBuilder/StringBuffer . As we remember, these classes do not actually differ, except that StringBufferthey are optimized for use in a multi-threaded environment, so StringBuilderthey work somewhat faster in single-threaded use. Based on this, today we will use StringBuilder. This class has many interesting methods, but specifically now we are interested in replace. StringBuilder replace(int start, int end, String str)— this method replaces characters in a substring of this sequence with characters in the specified string. The substring begins at the specified beginning and continues until the character at the end of the index, -1or until the end of the sequence if no such character exists. Let's look at an example:
StringBuilder strBuilder = new StringBuilder("Java Rush");
strBuilder.replace(5, 9, "God");
System.out.println(strBuilder);
Conclusion:
Java God
As you can see, we indicate the interval in which we want to write the string, and write a substring on top of what is in the interval. So, using the help, StringBuilderwe will recreate an analogue of the method replaceall java. How will it look like:
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();
}
It’s scary at first glance, but with a little understanding you can understand that everything is not so complicated and quite logical. We have three arguments:
  • str— a line in which we want to replace some substrings;
  • oldStr— representation of substrings that we will replace;
  • newStr- what we will replace it with.
ifWe need the first one to check the incoming data, and if the string stris either oldStrempty, or the new substring newStris equal to the old one oldStr, then executing the method will be meaningless. Therefore, we return the original string - str. Next, we check newStrfor null, and if this is the case, then we convert it into an empty string format that is more convenient for us - "". Then we have the declaration of the variables we need:
  • total string length str;
  • substring length oldStr;
  • object StringBuilderfrom a shared string.
We start a loop that should run a number of times equal to the length of the total string (but, most likely, this will never happen). Using the class method StringBuilder- indexOf- we find out the index of the first occurrence of the substring we are interested in. Unfortunately, I would like to note that it indexOfdoes not work with regular expressions, so our final method will only work with occurrences of strings (( If this index is equal to -1, then there are no more occurrences of these occurrences in the current object StringBuilder, so we exit the method with the result of interest: it is contained in our StringBuilder, which we convert to String, using toString. If our index is equal -1in the first iteration of the loop, then the substring that needs to be replaced was not in the general string initially. Therefore, in such a situation, we simply return the general string. Next we have and the method described above is used replacefor StringBuilderusing the found index of the occurrence to indicate the coordinates of the substring to be replaced. This loop will run as many times as substrings that need to be replaced are found. If the string consists only of the character that needs to be replaced, then only in this case we have The loop will run completely and we will get the result StringBuilderconverted to a string. We need to check the correctness of this method, right? Let's write a test that checks the operation of the method in various 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, "");
}
Can be divided into 7 separate tests, each of which will be responsible for its own test case. Having launched it, we will see that it is green, that is, successful. Well, that seems to be all. Although wait, we said above that this method will be much faster replaceAllthan String. Well, let's see:
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);
Next, this code was run three times and we got the following results: Console output:
Performance ratio  - 5.012148941181627
 
Performance ratio  - 5.320637176017641
 
Performance ratio  - 4.719192686500394
As we can see, on average our method is 5 times more productive than the classic replaceAllclass ! StringWell, finally, let's run the same check, but, so to speak, in vain. In other words, in the case when no match is found. Let's replace the search string from "tyu"to "--". Three runs yielded the following results: Console output:
Performance ratio  - 8.789647093542246
 
Performance ratio  - 9.177105482660881
 
Performance ratio  - 8.520964375227406
On average, performance for cases where no matches were found increased by 8.8 times! Replace string in Java - 4
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION