JavaRush /Java-Blog /Random-DE /String in Java ersetzen

String in Java ersetzen

Veröffentlicht in der Gruppe Random-DE
Bei der Arbeit eines Programmierers kommt es häufig vor, dass sich einige Aufgaben oder deren Bestandteile wiederholen. Deshalb möchte ich heute ein Thema ansprechen, das in der täglichen Arbeit eines jeden Java-Entwicklers häufig vorkommt. Zeichenfolge in Java ersetzen - 1Nehmen wir an, dass Sie von einer bestimmten Methode einen bestimmten String erhalten. Und alles daran scheint gut zu sein, aber es gibt eine Kleinigkeit, die nicht zu Ihnen passt. Beispielsweise ist das Trennzeichen nicht geeignet und Sie benötigen ein anderes (oder gar kein). Was kann man in einer solchen Situation tun? Nutzen Sie selbstverständlich die Methoden replaceder Klasse String.

Java-String ersetzen

Das Typobjekt Stringverfügt über vier Variationen der Ersetzungsmethode replace:
  • replace(char, char);
  • replace(CharSequence, CharSequence);
  • replaceFirst(String, String);
  • replaceAll(String, String).
Der Zweck all dieser Methoden ist derselbe: Ersetzen eines Teils einer Zeichenfolge durch eine andere Zeichenfolge. Schauen wir sie uns genauer an. 1.replace(char, char) String replace(char oldChar, char newChar) - ersetzt alle Vorkommen des Zeichens des ersten Arguments oldChardurch das zweite - newChar. In diesem Beispiel ersetzen wir das Komma durch ein Semikolon:
String value = "In JavaRush, Diego the best, Diego is Java God".replace(',', ';');
System.out.println(value);
Konsolenausgabe:
In JavaRush; Diego the best; Diego is Java God
2.replace(CharSequence, CharSequence) Ersetzt jede Teilzeichenfolge einer Zeichenfolge, die einer angegebenen Zeichenfolge entspricht, durch eine Folge von Ersatzzeichen.
String value = "In JavaRush, Diego the best, Diego is Java God".replace("Java", "Rush");
System.out.println(value);
Abschluss:
In RushRush, Diego the best, Diego is Rush God
3.replaceFirst(String, String) String replaceFirst(String regex, String replacement) – Ersetzt die erste Teilzeichenfolge, die mit dem angegebenen regulären Ausdruck übereinstimmt, durch eine Ersatzzeichenfolge. Wenn Sie einen ungültigen regulären Ausdruck verwenden, können Sie eine PatternSyntaxException abfangen (was keine gute Sache ist). In diesem Beispiel ersetzen wir den Namen des Champion-Roboters:
String value = "In JavaRush, Diego the best, Diego is Java God".replaceFirst("Diego", "Amigo");
System.out.println(value);
Konsolenausgabe:
In JavaRush, Amigo the best, Diego is Java God
Wie wir sehen, hat sich nur der erste Eintrag von „Diego“ geändert, die folgenden blieben jedoch weggelassen, also unangetastet. 4. replaceAll()in Java String replaceAll(String regex, String replacement) – diese Methode ersetzt alle Vorkommen eines Teilstrings in einem String regexdurch replacement. Als erstes Argument kann ein regulärer Ausdruck verwendet werden regex. Versuchen wir als Beispiel, die vorherige Ersetzung mit Namen durchzuführen, jedoch mit einer neuen Methode:
String value = "In JavaRush, Diego the best, Diego is Java God".replaceAll("Diego", "Amigo");
System.out.println(value);
Konsolenausgabe:
In JavaRush, Amigo the best, Amigo is Java God
Wie wir sehen können, wurden alle Symbole vollständig durch die erforderlichen ersetzt. Ich denke, Amigo wird sich freuen =)

Reguläre Ausdrücke

Oben wurde gesagt, dass es möglich ist, einen regulären Ausdruck zu verwenden. Lassen Sie uns zunächst selbst klären, was ein regulärer Ausdruck ist. Reguläre Ausdrücke sind eine formale Sprache zum Suchen und Bearbeiten von Teilzeichenfolgen in Texten, die auf der Verwendung von Metazeichen (Platzhaltern) basiert. Einfach ausgedrückt ist es ein Muster aus Zeichen und Metazeichen, das eine Suchregel definiert. Zum Beispiel: \D– eine Vorlage, die ein beliebiges nicht-digitales Zeichen beschreibt; \d– definiert ein beliebiges numerisches Zeichen, das auch als [0-9]; beschrieben werden kann. [a-zA-Z]– eine Vorlage, die lateinische Zeichen von a bis z beschreibt, ohne Berücksichtigung der Groß- und Kleinschreibung; Betrachten Sie die Anwendung in einer replaceAllKlassenmethode String:
String value = "In JavaRush, Diego the best, Diego is Java God".replaceAll("\\s[a-zA-Z]{5}\\s", " Amigo ");
System.out.println(value);
Konsolenausgabe:
In JavaRush, Amigo the best, Amigo is Java God
\\s[a-zA-Z]{5}\\s— beschreibt ein Wort aus 5 lateinischen Zeichen, umgeben von Leerzeichen. Dementsprechend wird diese Vorlage durch die von uns übergebene Zeichenfolge ersetzt.

Java-Regex ersetzen

Um reguläre Ausdrücke in Java zu verwenden, sind grundsätzlich die Fähigkeiten der java.util.regex. Die wichtigsten Klassen sind:
  1. Pattern– eine Klasse, die eine kompilierte Version eines regulären Ausdrucks bereitstellt.
  2. Matcher– Diese Klasse interpretiert das Muster und ermittelt Übereinstimmungen in der empfangenen Zeichenfolge.
Normalerweise arbeiten diese beiden Klassen zusammen. Wie wird also unser vorheriges Objekt aussehen, aber mit Hilfe von Matcherund 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);
Und unsere Schlussfolgerung wird dieselbe sein:
In JavaRush, Amigo the best, Amigo is Java God
Weitere Informationen zu regulären Ausdrücken finden Sie in diesem Artikel .

Alternative zu replaceAll

Es besteht kein Zweifel, dass die Methoden sehr beeindruckend replacesind String, aber man kann die Tatsache nicht ignorieren, dass Stringes sich um immutableein Objekt handelt, das heißt, es kann nach seiner Erstellung nicht geändert werden. Wenn wir also einige Teile einer Zeichenfolge mithilfe von Methoden ersetzen replace, ändern wir das Objekt nicht String, sondern erstellen jedes Mal ein neues mit den erforderlichen Inhalten. Aber jedes Mal ein neues Objekt zu erstellen, dauert lange, nicht wahr? Vor allem, wenn es nicht um ein paar Objekte geht, sondern um ein paar Hunderte oder sogar Tausende. Sie fangen wohl oder übel an, über Alternativen nachzudenken. Und welche Alternativen haben wir? Zeichenfolge in Java ersetzen - 2Hmm... Wenn es um Stringseine Eigenschaft geht immutable, denkt man sofort an Alternativen, aber nicht immutable, nämlich StringBuilder/StringBuffer . Wie wir uns erinnern, unterscheiden sich diese Klassen eigentlich nicht, außer dass StringBuffersie für den Einsatz in einer Multithread-Umgebung optimiert sind, sodass StringBuildersie im Single-Threaded-Einsatz etwas schneller arbeiten. Auf dieser Grundlage werden wir heute diese Klasse verwenden, die StringBuilder. viele interessante Methoden hat, aber jetzt interessieren wir uns speziell für replace. StringBuilder replace(int start, int end, String str)– Diese Methode ersetzt Zeichen in einer Teilzeichenfolge dieser Sequenz durch Zeichen in der angegebenen Zeichenfolge. Die Teilzeichenfolge beginnt am angegebenen Anfang und wird bis zum Zeichen am Ende des Index -1oder bis zum Ende der Sequenz fortgesetzt, wenn kein solches Zeichen vorhanden ist. Schauen wir uns ein Beispiel an:
StringBuilder strBuilder = new StringBuilder("Java Rush");
strBuilder.replace(5, 9, "God");
System.out.println(strBuilder);
Abschluss:
Java God
Wie Sie sehen, geben wir das Intervall an, in dem wir die Zeichenfolge schreiben möchten, und schreiben eine Teilzeichenfolge über den Inhalt des Intervalls. Mithilfe der Hilfe StringBuilderwerden wir also ein Analogon der Methode nachbilden replaceall java. Wie wird es aussehen:
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();
}
Auf den ersten Blick ist es beängstigend, aber mit ein wenig Verständnis kann man verstehen, dass nicht alles so kompliziert und ganz logisch ist. Wir haben drei Argumente:
  • str— eine Zeile, in der wir einige Teilzeichenfolgen ersetzen möchten;
  • oldStr— Darstellung von Teilzeichenfolgen, die wir ersetzen werden;
  • newStr- womit wir es ersetzen werden.
ifWir benötigen die erste, um die eingehenden Daten zu überprüfen. Wenn die Zeichenfolge strentweder oldStrleer ist oder die neue Teilzeichenfolge newStrmit der alten übereinstimmt oldStr, ist die Ausführung der Methode bedeutungslos. Daher geben wir die ursprüngliche Zeichenfolge zurück - str. Als nächstes suchen wir newStrnach null, und wenn dies der Fall ist, konvertieren wir es in ein leeres String-Format, das für uns bequemer ist – "". Dann haben wir die Deklaration der Variablen, die wir brauchen:
  • Gesamtlänge der Zeichenfolge str;
  • Teilstringlänge oldStr;
  • Objekt StringBuilderaus einer gemeinsam genutzten Zeichenfolge.
Wir starten eine Schleife, die so oft ausgeführt werden sollte, wie die gesamte Zeichenfolge lang ist (was aber höchstwahrscheinlich nie passieren wird). StringBuilderMit der Klassenmethode indexOfermitteln wir den Index des ersten Vorkommens des Teilstrings, der uns interessiert. Leider möchte ich anmerken, dass es indexOfnicht mit regulären Ausdrücken funktioniert, sodass unsere endgültige Methode nur mit Vorkommen von Zeichenfolgen funktioniert (( Wenn dieser Index gleich ist -1, dann gibt es im aktuellen Objekt keine Vorkommen dieser Vorkommen mehr StringBuilder. Also beenden wir die Methode mit dem Ergebnis von Interesse: Es ist in unserem enthalten StringBuilder, das wir Stringmithilfe von in umwandeln toString. Wenn unser Index -1in der ersten Iteration der Schleife gleich ist, befand sich der zu ersetzende Teilstring nicht im Allgemeinen Daher geben wir in einer solchen Situation einfach die allgemeine Zeichenfolge zurück. Als nächstes verwenden wir die oben beschriebene Methode, replaceum StringBuilderden gefundenen Index des Vorkommens zu verwenden, um die Koordinaten der zu ersetzenden Teilzeichenfolge anzugeben. Diese Schleife wird ausgeführt so oft wie Teilzeichenfolgen gefunden werden, die ersetzt werden müssen. Wenn die Zeichenfolge nur aus dem Zeichen besteht, das ersetzt werden muss, dann haben wir nur in diesem Fall die Schleife vollständig durchlaufen und das Ergebnis wird in StringBuildereine Zeichenfolge umgewandelt. Wir müssen die Richtigkeit dieser Methode überprüfen, oder? Schreiben wir einen Test, der die Funktionsweise der Methode in verschiedenen Situationen überprüft:
@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, "");
}
Kann in 7 separate Tests unterteilt werden, von denen jeder für seinen eigenen Testfall verantwortlich ist. Nachdem wir es auf den Markt gebracht haben, werden wir sehen, dass es grün, also erfolgreich ist. Nun, das scheint alles zu sein. Obwohl wir warten, haben wir oben gesagt, dass diese Methode viel schneller sein wird replaceAllals String. Nun, werfen wir einen Blick darauf:
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);
Als nächstes wurde dieser Code dreimal ausgeführt und wir erhielten die folgenden Ergebnisse: Konsolenausgabe:
Performance ratio  - 5.012148941181627
 
Performance ratio  - 5.320637176017641
 
Performance ratio  - 4.719192686500394
Wie wir sehen können, ist unsere Methode im Durchschnitt fünfmal produktiver als die klassische replaceAllKlasse ! StringLassen Sie uns zum Schluss noch einmal die gleiche Prüfung durchführen, aber sozusagen vergeblich. Mit anderen Worten, für den Fall, dass keine Übereinstimmung gefunden wird. Ersetzen wir die Suchzeichenfolge von "tyu"durch "--". Drei Durchläufe ergaben folgende Ergebnisse: Konsolenausgabe:
Performance ratio  - 8.789647093542246
 
Performance ratio  - 9.177105482660881
 
Performance ratio  - 8.520964375227406
Im Durchschnitt stieg die Leistung in Fällen, in denen keine Übereinstimmungen gefunden wurden, um das 8,8-fache! Zeichenfolge in Java ersetzen - 4
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION