Was bedeutet Ersetzen, wenn keine Übereinstimmung gefunden wird? (unter der Haube)

8

Ich habe sehr lange Zeichenketten, die ein Muster entfernen müssen, wenn es erscheint. Aber es ist ein unglaublich seltener Grenzfall für das Erscheinen in den Streichern.

Wenn ich das tue:

%Vor%

Dann sieht es so aus, als würde ich eine neue Zeichenfolge erstellen (weil Java-Strings unveränderlich sind), was eine Verschwendung wäre, wenn die ursprüngliche Zeichenfolge in Ordnung wäre. Sollte ich zuerst nach einer Übereinstimmung suchen und dann nur ersetzen, wenn eine Übereinstimmung gefunden wird?

    
ColBeseder 05.11.2014, 06:26
quelle

3 Antworten

10

Kurze Antwort

Wenn die Dokumentation verschiedener Implementierungen überprüft wird, scheint keine Methode String.replace(CharSequence, CharSequence) erforderlich zu sein, um die gleiche Zeichenfolge zurückzugeben, wenn keine Übereinstimmung gefunden wird.

Ohne die Anforderung aus der Dokumentation kann die Implementierung die Methode optimieren oder nicht, falls keine Übereinstimmung gefunden wird. Es ist am besten, Ihren Code so zu schreiben, als ob es keine Optimierung geben würde Stellen Sie sicher, dass es in jeder Implementierung oder Version von JRE ordnungsgemäß ausgeführt wird.

Wenn keine Übereinstimmung gefunden wird, gibt die Oracle-Implementierung (Version 8-b123) das gleiche String-Objekt zurück, während GNU Classpath (Version 0.95) unabhängig davon ein neues String-Objekt zurückgibt.

Wenn Sie in einer der Dokumentation eine Klausel finden, die String.replace(CharSequence, CharSequence) benötigt, um dasselbe String -Objekt zurückzugeben, wenn keine Übereinstimmung gefunden wird, hinterlassen Sie bitte einen Kommentar.

Lange Antwort

  

Die lange Antwort unten zeigt, dass verschiedene Implementierungen den Fall, in dem keine Übereinstimmung gefunden wird, optimieren können oder nicht.

Schauen wir uns die Implementierung von Oracle und die Implementierung von String.replace(CharSequence, CharSequence) in GNU Classpath an.

GNU Klassenpfad

  

Hinweis : Dies ist zum Zeitpunkt des Schreibens korrekt. Auch wenn sich der Link in Zukunft wahrscheinlich nicht ändert, wird der Inhalt des Links wahrscheinlich in eine neuere Version von GNU Classpath geändert und kann mit dem unten angegebenen Inhalt nicht mehr synchron sein. Wenn sich die Änderung auf die Richtigkeit auswirkt, hinterlassen Sie bitte einen Kommentar.

Schauen wir uns GNU Classpath's Implementierung von String.replace(CharSequence, CharSequence) an (Version 0.95 zitiert).

%Vor%

Überprüfen wir den Quellcode von StringBuilder.toString() . Da dies den Rückgabewert bestimmt, wenn StringBuilder.toString() den Puffer kopiert, müssen wir keinen weiteren Code weiter oben überprüfen.

%Vor%

Wenn Sie die Dokumentation nicht überzeugen kann, folgen Sie einfach dem String -Konstruktor. Schließlich wird der nicht öffentliche Konstruktor String(char[], int, int, boolean) aufgerufen, mit Die boolean dont_copy wurde auf false gesetzt, was bedeutet, dass die neue String den Puffer kopieren muss.

%Vor%

Diese Beweise legen nahe, dass die Implementierung von String.replace(CharSequence, CharSequence) in GNU Classpath nicht dieselbe Zeichenfolge zurückgibt.

Oracle

In der Oracle-Implementierung String.replace(CharSequence, CharSequence) (Version 8-b123 zitiert), die Methode verwendet Pattern class, um die Ersetzung durchzuführen.

%Vor%

Matcher.replaceAll(String) ruft toString() function für CharSequence auf und gibt es zurück, wenn keine Übereinstimmung gefunden wird:

%Vor%

String implementiert die CharSequence -Schnittstelle und Da sich der String selbst in Matcher übergibt, sehen wir uns String.toString :

%Vor%

Daraus können wir schließen, dass Oracles Implementierung denselben String zurückgibt, wenn keine Übereinstimmung gefunden wird.

    
nhahtdh 05.11.2014, 12:14
quelle
2

Ich habe keine definitive Antwort (aus den Dokumenten) gefunden, aber ich habe das auf Oracle's JRE7 ausprobiert und festgestellt, dass replace eine Referenz an dieselbe Zeichenfolge zurückgegeben hat.

Hier ist der Code, den ich zum Testen verwendet habe:

%Vor%

Aber ich wäre daran interessiert, einige Benchmarks von replace vs contains zu sehen, um sicher zu sein, ob es einen Vorteil gibt.

    
ColBeseder 05.11.2014 06:26
quelle
1

Ok .. In Java 8. Das passiert, wenn Sie myString.replace() aufrufen.

%Vor%

Pattern.compile(target.toString(), Pattern.LITERAL).matcher( this) Die Zielzeichenfolge wird als Literal -Muster kompiliert. und matcher() wird aufgerufen, indem die aufrufende stringInstance an sie übergeben wird.

Die Methode "matcher ()" gibt nun einen neuen Matcher zurück. Beachten Sie, dass das text -Feld von matcher das aktuelle Objekt ( this ) ist, d. H. Das String-Objekt, auf dem replace() aufgerufen wurde.

Als nächstes haben wir in replaceAll() folgenden Code:         boolean result = find();

d. h.

%Vor%     
TheLostMind 05.11.2014 06:33
quelle