JavaRush /Java Blog /Random-TW /Java中替換字串

Java中替換字串

在 Random-TW 群組發布
在程式設計師的工作中,經常會重複某些任務或其元件。因此,今天我想談談 Java 開發人員日常工作中經常遇到的一個主題。 在 Java 中替換字串 - 1假設您從某個方法收到某個字串。而且一切看起來都不錯,但有一些小地方不太適合你。例如,分隔符號不合適,您需要其他分隔符號(或根本不需要)。在這種情況下可以做些什麼呢?replace自然地,使用類別的方法String

Java字串替換

類型物件String有四種替換方法replace
  • replace(char, char);
  • replace(CharSequence, CharSequence);
  • replaceFirst(String, String);
  • replaceAll(String, String).
所有這些方法的目的都是相同的——用另一個字串替換字串的一部分。讓我們仔細看看它們。 1.replace(char, char) -用第二個 -String replace(char oldChar, char newChar)取代第一個參數中所有出現的字元。在此範例中,我們將用分號替換逗號: oldCharnewChar
String value = "In JavaRush, Diego the best, Diego is Java God".replace(',', ';');
System.out.println(value);
控制台輸出:
In JavaRush; Diego the best; Diego is Java God
2.replace(CharSequence, CharSequence) 將字串中與指定字元序列相符的每個子字串替換為替換字元序列。
String value = "In JavaRush, Diego the best, Diego is Java God".replace("Java", "Rush");
System.out.println(value);
結論:
In RushRush, Diego the best, Diego is Rush God
3.replaceFirst(String, String) String replaceFirst(String regex, String replacement) - 用替換字串取代與指定正規表示式相符的第一個子字串。當使用無效的正規表示式時,您可以捕獲PatternSyntaxException(這不是一件好事)。在此範例中,我們替換冠軍機器人的名稱:
String value = "In JavaRush, Diego the best, Diego is Java God".replaceFirst("Diego", "Amigo");
System.out.println(value);
控制台輸出:
In JavaRush, Amigo the best, Diego is Java God
正如我們所看到的,只有「Diego」的第一個出現發生了變化,但後續的出現仍然被遺漏——也就是說,沒有受到影響。 4.replaceAll()在 Java 中 String replaceAll(String regex, String replacement)- 此方法將字串中所有出現的子字串替換regexreplacement. 正規表示式可以用作第一個參數regex。作為範例,讓我們嘗試使用新方法執行先前的名稱替換:
String value = "In JavaRush, Diego the best, Diego is Java God".replaceAll("Diego", "Amigo");
System.out.println(value);
控制台輸出:
In JavaRush, Amigo the best, Amigo is Java God
正如我們所看到的,所有符號都已完全替換為必要的符號。我想阿米戈會很高興 =)

常用表達

上面說了可以用正規表示式來替換。首先我們先來明確一下什麼是正規表示式? 正規表示式是一種基於元字元(通配符)的使用來搜尋和操作文字中子字串的形式語言。簡而言之,它是定義搜尋規則的字元和元字元的模式。例如: \D- 描述任何非數字字元的模板; \d— 定義任意數字字符,也可以描述為[0-9][a-zA-Z]— 描述從 a 到 z 的拉丁字符的模板,不區​​分大小寫;replaceAll考慮在類別方法中的應用String
String value = "In JavaRush, Diego the best, Diego is Java God".replaceAll("\\s[a-zA-Z]{5}\\s", " Amigo ");
System.out.println(value);
控制台輸出:
In JavaRush, Amigo the best, Amigo is Java God
\\s[a-zA-Z]{5}\\s— 描述由 5 個拉丁字元組成且周圍有空格的單字。因此,該模板將替換為我們傳遞的字串。

Java正規表示式替換

基本上,要在 Java 中使用正規表示式,java.util.regex. 關鍵類別是:
  1. Pattern- 提供正規表示式的編譯版本的類別。
  2. Matcher— 此類解釋模式並決定其接收的字串中的符合項目。
通常,這兩個類別一起工作。Matcher那麼,在and的幫助下,我們之前的對象會是什麼樣子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);
我們的結論是一樣的:
In JavaRush, Amigo the best, Amigo is Java God
您可以在本文中閱讀有關正規表示式的更多資訊。

替換全部的替代方案

毫無疑問,這些方法replace非常令人印象深刻,但我們不能忽視它是一個物件的String事實,即它在創建後就無法更改。因此,當我們使用方法替換字串的某些部分時,我們不會更改對象,而是每次創建一個新對象,並包含必要的內容。但是每次創建一個新物件需要很長時間,不是嗎?特別是當問題不是幾個對象,而是數百個甚至數千個時。無論你願意與否,你開始考慮替代方案。我們還有什麼選擇?嗯...說到它的屬性,你立刻就會想到替代方案,但不是,即StringBuilder/StringBuffer。正如我們所記得的,這些類別實際上並沒有什麼不同,只是它們針對多執行緒環境中的使用進行了最佳化,因此它們在單執行緒使用中運行得更快一些。基於此,今天我們將使用 這個類別有很多有趣的方法,但具體來說現在我們感興趣的是。 — 此方法將此序列的子字串中的字元替換為指定字串中的字元。子字串從指定的開頭開始,一直持續到索引末尾的字符,或者如果不存在這樣的字符,則一直到序列的末尾。讓我們來看一個例子: StringimmutablereplaceString在 Java 中替換字串 - 2StringimmutableimmutableStringBufferStringBuilderStringBuilder.replaceStringBuilder replace(int start, int end, String str)-1
StringBuilder strBuilder = new StringBuilder("Java Rush");
strBuilder.replace(5, 9, "God");
System.out.println(strBuilder);
結論:
Java God
如您所看到的,我們指示要寫入字串的區間,並在區間內的內容之上寫入一個子字串。因此,使用幫助,StringBuilder我們將重新創建該方法的類似物replaceall java。它會是什麼樣子:
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();
}
乍看很嚇人,但稍微了解一下你就會明白,一切並沒有那麼複雜,而且很有邏輯性。我們有三個論點:
  • str— 我們想要替換一些子字串的行;
  • oldStr— 我們將替換的子字串的表示;
  • newStr- 我們將用什麼來替換它。
if我們需要第一個來檢查傳入的數據,如果字串stroldStr空,或者新的子字串newStr等於舊的子字串oldStr,那麼執行該方法將毫無意義。因此,我們返回原始字串 - str。接下來,我們檢查newStrnull如果是這種情況,那麼我們將其轉換為對我們來說更方便的空字串格式 - ""。然後我們就有了我們需要的變數的聲明:
  • 字串總長度str
  • 子串長度oldStr
  • StringBuilder來自共享字串的物件。
我們啟動一個循環,該循環的運行次數應等於總字串的長度(但是,很可能,這永遠不會發生)。使用類別方法StringBuilder- indexOf- 我們找出我們感興趣的子字串第一次出現的索引。不幸的是,我想指出它indexOf不適用於正則表達式,因此我們的最終方法僅適用於字串的出現((如果該索引等於-1,則當前物件中不再出現這些出現StringBuilder,因此,我們帶著感興趣的結果退出該方法:它包含在our 中StringBuilder,我們String使用轉換為toString。如果我們的索引在循環的第一次迭代中相等-1,則需要替換的子字串不在一般字串中字串最初。因此,在這種情況下,我們只需返回通用字串。接下來我們使用上面描述的方法,使用replace找到StringBuilder的出現的索引來指示要替換的子字串的座標。這個循環將運行找到需要替換的子字元串的次數一樣多,如果字串只包含需要替換的字符,那麼只有在這種情況下我們的循環才會完整運行,我們將得到轉換為StringBuilder字串的結果。我們需要檢查這個方法的正確性,對嗎?讓我們編寫一個測試來檢查該方法在各種情況下的操作:
@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, "");
}
可以分為7個獨立的測試,每個測試都會負責自己的測試案例。啟動後,我們會看到它是綠色的,也就是成功的。嗯,似乎就是這樣。雖然等等,我們上面說過這個方法會replaceAllString. 好吧,讓我們來看看:
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);
接下來,程式碼運行了 3 次,我們得到了以下結果: 控制台輸出:
Performance ratio  - 5.012148941181627
 
Performance ratio  - 5.320637176017641
 
Performance ratio  - 4.719192686500394
正如我們所看到的,我們的方法平均效率是經典replaceAll類別的String5 倍!好吧,最後,讓我們進行同樣的檢查,但是,可以說,是徒勞的。換句話說,在沒有找到匹配項的情況下。讓我們將搜尋字串從 替換"tyu""--"。三次運行產生以下結果: 控制台輸出:
Performance ratio  - 8.789647093542246
 
Performance ratio  - 9.177105482660881
 
Performance ratio  - 8.520964375227406
平均而言,未找到匹配項的情況下的效能提高了 8.8 倍! 在 Java 中替換字串 - 4
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION