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?
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.
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.
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).
Ü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.
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.
Diese Beweise legen nahe, dass die Implementierung von String.replace(CharSequence, CharSequence)
in GNU Classpath nicht dieselbe Zeichenfolge zurückgibt.
In der Oracle-Implementierung String.replace(CharSequence, CharSequence)
(Version 8-b123 zitiert), die Methode verwendet Pattern
class, um die Ersetzung durchzuführen.
Matcher.replaceAll(String)
ruft toString()
function für CharSequence
auf und gibt es zurück, wenn keine Übereinstimmung gefunden wird:
String
implementiert die CharSequence
-Schnittstelle und Da sich der String selbst in Matcher
übergibt, sehen wir uns String.toString
:
Daraus können wir schließen, dass Oracles Implementierung denselben String zurückgibt, wenn keine Übereinstimmung gefunden wird.
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.
Ok .. In Java 8. Das passiert, wenn Sie myString.replace()
aufrufen.
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%Tags und Links string java regex performance replace