Quelle est l'importance de la Pattern.compile()
méthode?
Pourquoi dois-je compiler la chaîne de regex avant d'obtenir l' Matcher
objet?
Par exemple :
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)
au lieu d'une fonction de compilation statique. Le commentaire des marcolopes est sur place.Réponses:
La
compile()
méthode est toujours appelée à un moment donné; c'est la seule façon de créer un objet Pattern. La question est donc vraiment, pourquoi devriez-vous l'appeler explicitement ? L'une des raisons est que vous avez besoin d'une référence à l'objet Matcher afin de pouvoir utiliser ses méthodes, commegroup(int)
pour récupérer le contenu des groupes de capture. La seule façon d'obtenir un objet Matcher est d'utiliser lamatcher()
méthode de l'objet Pattern , et la seule façon d'obtenir un objet Pattern est d'utiliser lacompile()
méthode. Ensuite, il y a lafind()
méthode qui, contrairement àmatches()
, n'est pas dupliquée dans les classes String ou Pattern.L'autre raison est d'éviter de créer encore et encore le même objet Pattern. Chaque fois que vous utilisez l'une des méthodes basées sur les regex dans String (ou la
matches()
méthode statique dans Pattern), cela crée un nouveau Pattern et un nouveau Matcher. Donc, cet extrait de code:... est exactement équivalent à ceci:
De toute évidence, cela fait beaucoup de travail inutile. En fait, la compilation de l'expression rationnelle et l'instanciation de l'objet Pattern peuvent facilement prendre plus de temps que pour effectuer une correspondance réelle. Il est donc généralement logique de sortir cette étape de la boucle. Vous pouvez également créer le Matcher à l'avance, bien qu'ils ne soient pas si chers:
Si vous êtes familier avec les expressions rationnelles .NET, vous vous demandez peut-être si la
compile()
méthode de Java est liée auRegexOptions.Compiled
modificateur de .NET ; La réponse est non. LaPattern.compile()
méthode de Java est simplement équivalente au constructeur Regex de .NET. Lorsque vous spécifiez l'Compiled
option:... il compile le regex directement en code d'octet CIL, ce qui lui permet de fonctionner beaucoup plus rapidement, mais à un coût important en traitement initial et en utilisation de la mémoire - pensez-y comme des stéroïdes pour les expressions régulières. Java n'a pas d'équivalent; il n'y a aucune différence entre un motif créé en coulisse par
String#matches(String)
et un avec lequel vous créez explicitementPattern#compile(String)
.(EDIT: J'ai dit à l'origine que tous les objets .NET Regex sont mis en cache, ce qui est incorrect. Depuis .NET 2.0, la mise en cache automatique se produit uniquement avec des méthodes statiques comme
Regex.Matches()
, pas lorsque vous appelez directement un constructeur Regex. Ref )la source
reset
un objet Matcher qui n'est jamais utilisé par un seul thread à la fois afin de réduire les allocations.Compile analyse l'expression régulière et crée une représentation en mémoire . La surcharge à compiler est significative par rapport à une correspondance. Si vous utilisez un modèle à plusieurs reprises, il gagnera en performances pour mettre en cache le modèle compilé.
la source
Lorsque vous compilez,
Pattern
Java effectue des calculs pourString
accélérer la recherche de correspondances dans s. (Construit une représentation en mémoire de l'expression régulière)Si vous comptez réutiliser le
Pattern
plusieurs fois, vous verrez une augmentation considérable des performances par rapport à la création d'un nouveau àPattern
chaque fois.Dans le cas où vous n'utilisez le Pattern qu'une seule fois, l'étape de compilation semble être une ligne de code supplémentaire, mais, en fait, elle peut être très utile dans le cas général.
la source
Matcher matched = Pattern.compile(regex).matcher(text);
. Il y a des avantages à cela par rapport à l'introduction d'une seule méthode: les arguments sont nommés efficacement et il est évident comment prendre en compte lesPattern
pour de meilleures performances (ou les répartir entre les méthodes).C'est une question de performances et d'utilisation de la mémoire, compilez et conservez le modèle respecté si vous avez besoin de l'utiliser beaucoup. Une utilisation typique de l'expression régulière est de valider l' entrée utilisateur (format) , et également de formater les données de sortie pour les utilisateurs , dans ces classes, l'enregistrement du modèle respecté semble assez logique, car ils appellent généralement beaucoup.
Vous trouverez ci-dessous un exemple de validateur, qui s'appelle beaucoup :)
Comme mentionné par @Alan Moore, si vous avez des regex réutilisables dans votre code, (avant une boucle par exemple), vous devez compiler et enregistrer le modèle pour le réutiliser.
la source
Pattern.compile()
permet de réutiliser une regex plusieurs fois (c'est threadsafe). L'avantage en termes de performances peut être assez important.J'ai fait un benchmark rapide:
compileOnce était entre 3x et 4x plus rapide . Je suppose que cela dépend fortement de la regex elle-même mais pour une regex qui est souvent utilisée, je vais pour une
static Pattern pattern = Pattern.compile(...)
la source
La pré-compilation de l'expression régulière augmente la vitesse. La réutilisation du Matcher vous donne une autre légère accélération. Si la méthode est appelée fréquemment, disons qu'elle est appelée dans une boucle, les performances globales augmenteront certainement.
la source
Similaire à 'Pattern.compile', il y a 'RECompiler.compile' [de com.sun.org.apache.regexp.internal] où:
1. le code compilé pour pattern [az] contient 'az'
2. le code compilé pour le motif [0-9] contient '09'
3. le code compilé pour pattern [abc] a 'aabbcc' dedans.
Ainsi, le code compilé est un excellent moyen de généraliser plusieurs cas. Ainsi au lieu d'avoir des situations de gestion de code différentes 1, 2 et 3. Le problème se réduit à comparer avec l'ascii de l'élément présent et suivant dans le code compilé, d'où les paires. Ainsi
a. tout ce qui a ascii entre a et z est compris entre a et z
b. tout ce qui a ascii entre 'a et a est définitivement' a '
la source
La classe Pattern est le point d'entrée du moteur regex. Vous pouvez l'utiliser via Pattern.matches () et Pattern.comiple (). # Différence entre ces deux. matches () - pour vérifier rapidement si un texte (String) correspond à une expression régulière donnée comiple () - crée la référence de Pattern. Vous pouvez donc utiliser plusieurs fois pour faire correspondre l'expression régulière à plusieurs textes.
Pour référence:
la source