Welche Bedeutung hat die Pattern.compile()
Methode?
Warum muss ich die Regex-Zeichenfolge kompilieren, bevor ich das Matcher
Objekt erhalte ?
Zum Beispiel :
String regex = "((\\S+)\\s*some\\s*";
Pattern pattern = Pattern.compile(regex); // why do I need to compile
Matcher matcher = pattern.matcher(text);
new Pattern(regex)
anstelle einer statischen Kompilierungsfunktion verwenden können. marcolopes Kommentar ist vor Ort.Antworten:
Die
compile()
Methode wird immer irgendwann aufgerufen; Dies ist die einzige Möglichkeit, ein Musterobjekt zu erstellen. Die Frage ist also wirklich, warum Sie es explizit nennen sollten . Ein Grund dafür ist, dass Sie einen Verweis auf das Matcher-Objekt benötigen, damit Sie dessen Methoden verwenden können,group(int)
um beispielsweise den Inhalt von Erfassungsgruppen abzurufen. Die einzige Möglichkeit, das Matcher-Objekt in den Griff zu bekommen, ist diematcher()
Methode des Pattern-Objekts , und die einzige Möglichkeit, das Pattern-Objekt in den Griff zu bekommen, ist diecompile()
Methode. Dann gibt es diefind()
Methode, die im Gegensatz zumatches()
den Klassen String oder Pattern nicht dupliziert wird.Der andere Grund besteht darin, zu vermeiden, dass immer wieder dasselbe Musterobjekt erstellt wird. Jedes Mal, wenn Sie eine der regex-basierten Methoden in String (oder die statische
matches()
Methode in Pattern) verwenden, werden ein neues Pattern und ein neuer Matcher erstellt. Also dieses Code-Snippet:... ist genau gleichbedeutend damit:
Das macht natürlich viel unnötige Arbeit. Tatsächlich kann das Kompilieren des regulären Ausdrucks und das Instanziieren des Musterobjekts leicht länger dauern als das Durchführen einer tatsächlichen Übereinstimmung. Daher ist es normalerweise sinnvoll, diesen Schritt aus der Schleife zu ziehen. Sie können den Matcher auch im Voraus erstellen, obwohl er bei weitem nicht so teuer ist:
Wenn Sie mit .NET-Regexen vertraut sind, fragen Sie sich möglicherweise, ob die Java-
compile()
Methode mit dem .NET-RegexOptions.Compiled
Modifikator zusammenhängt. Die Antwort ist nein. Die Java-Pattern.compile()
Methode entspricht lediglich dem Regex-Konstruktor von .NET. Wenn Sie dieCompiled
Option angeben :... kompiliert den regulären Ausdruck direkt in CIL-Bytecode, wodurch er eine viel schnellere Leistung erbringt, jedoch zu erheblichen Kosten bei der Vorabverarbeitung und der Speichernutzung - stellen Sie sich ihn als Steroide für reguläre Ausdrücke vor. Java hat kein Äquivalent; Es gibt keinen Unterschied zwischen einem Muster, das hinter den Kulissen erstellt wurde,
String#matches(String)
und einem Muster, mit dem Sie explizit erstellenPattern#compile(String)
.(BEARBEITEN: Ich habe ursprünglich gesagt, dass alle .NET Regex-Objekte zwischengespeichert werden, was falsch ist. Seit .NET 2.0 erfolgt das automatische Caching nur mit statischen Methoden wie
Regex.Matches()
, nicht wenn Sie einen Regex-Konstruktor direkt aufrufen. Ref )quelle
reset
ein Matcher-Objekt verwenden, das immer nur von einem Thread gleichzeitig verwendet wird, um die Zuordnungen zu reduzieren.Compile analysiert den regulären Ausdruck und erstellt eine speicherinterne Darstellung . Der zu kompilierende Aufwand ist im Vergleich zu einer Übereinstimmung erheblich. Wenn Sie ein Muster wiederholt verwenden , wird die Leistung zum Zwischenspeichern des kompilierten Musters verbessert.
quelle
Beim Kompilieren führt
Pattern
Java einige Berechnungen durch, um das Finden von Übereinstimmungen inString
s zu beschleunigen. (Erstellt eine speicherinterne Darstellung des regulären Ausdrucks)Wenn Sie die
Pattern
Mehrfachverwendung wiederverwenden, wird die Leistung erheblich gesteigert, wenn SiePattern
jedes Mal eine neue erstellen .Wenn Sie das Muster nur einmal verwenden, scheint der Kompilierungsschritt nur eine zusätzliche Codezeile zu sein, kann jedoch im allgemeinen Fall sehr hilfreich sein.
quelle
Matcher matched = Pattern.compile(regex).matcher(text);
. Dies hat gegenüber der Einführung einer einzelnen Methode Vorteile: Die Argumente werden effektiv benannt, und es ist offensichtlich, wie diePattern
für eine bessere Leistung herausgerechnet werden kann (oder auf mehrere Methoden aufgeteilt werden kann).Es ist eine Frage der Leistung und der Speichernutzung. Kompilieren und behalten Sie das konforme Muster, wenn Sie es häufig verwenden müssen. Eine typische Verwendung von Regex besteht darin, Benutzereingaben (Format) zu validieren und Ausgabedaten für Benutzer in diesen Klassen zu formatieren. Das Speichern des übereinstimmenden Musters erscheint ziemlich logisch, da sie normalerweise häufig aufgerufen werden.
Unten ist ein Beispielvalidator, der wirklich viel genannt wird :)
Wie von @Alan Moore erwähnt, müssen Sie Muster für die Wiederverwendung kompilieren und speichern, wenn Sie wiederverwendbaren regulären Ausdruck in Ihrem Code haben (z. B. vor einer Schleife).
quelle
Pattern.compile()
Erlauben Sie die mehrfache Wiederverwendung eines regulären Ausdrucks (es ist threadsicher). Der Leistungsvorteil kann erheblich sein.Ich habe einen schnellen Benchmark durchgeführt:
compileOnce war zwischen 3x und 4x schneller . Ich denke, es hängt stark von der Regex selbst ab, aber für eine Regex, die oft verwendet wird, entscheide ich mich für eine
static Pattern pattern = Pattern.compile(...)
quelle
Das Vorkompilieren des regulären Ausdrucks erhöht die Geschwindigkeit. Die Wiederverwendung des Matchers führt zu einer weiteren leichten Beschleunigung. Wenn die Methode häufig aufgerufen wird und beispielsweise innerhalb einer Schleife aufgerufen wird, steigt die Gesamtleistung mit Sicherheit.
quelle
Ähnlich wie bei 'Pattern.compile' gibt es 'RECompiler.compile' [von com.sun.org.apache.regexp.internal], wobei:
1. kompilierter Code für Muster [az] 'az' enthält
2. kompilierter Code für Muster [0-9] enthält '09'.
3. Kompilierter Code für Muster [abc] enthält 'aabbcc'.
Kompilierter Code ist daher eine großartige Möglichkeit, mehrere Fälle zu verallgemeinern. Anstatt also unterschiedliche Codebehandlungssituationen 1,2 und 3 zu haben. Das Problem reduziert sich auf den Vergleich mit den ASCII des gegenwärtigen und nächsten Elements im kompilierten Code, daher die Paare. Also
a. alles mit ascii zwischen a und z liegt zwischen a und z
b. alles mit ascii zwischen 'a und a' ist definitiv 'a'
quelle
Die Musterklasse ist der Einstiegspunkt der Regex-Engine. Sie können sie über Pattern.matches () und Pattern.comiple () verwenden. #Differenz zwischen diesen beiden. matches () - für schnell überprüfen , ob ein Text (String) einen bestimmten regulären Ausdruck comiple () - erstellen die Referenz - Muster. Kann also mehrmals verwendet werden, um den regulären Ausdruck mit mehreren Texten abzugleichen.
Als Referenz:
quelle