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, comme group(int)
pour récupérer le contenu des groupes de capture. La seule façon d'obtenir un objet Matcher est d'utiliser la matcher()
méthode de l'objet Pattern , et la seule façon d'obtenir un objet Pattern est d'utiliser la compile()
méthode. Ensuite, il y a la find()
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:
for (String s : myStringList) {
if ( s.matches("\\d+") ) {
doSomething();
}
}
... est exactement équivalent à ceci:
for (String s : myStringList) {
if ( Pattern.compile("\\d+").matcher(s).matches() ) {
doSomething();
}
}
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:
Pattern p = Pattern.compile("\\d+");
Matcher m = p.matcher("");
for (String s : myStringList) {
if ( m.reset(s).matches() ) {
doSomething();
}
}
Si vous êtes familier avec les expressions rationnelles .NET, vous vous demandez peut-être si la compile()
méthode de Java est liée au RegexOptions.Compiled
modificateur de .NET ; La réponse est non. La Pattern.compile()
méthode de Java est simplement équivalente au constructeur Regex de .NET. Lorsque vous spécifiez l' Compiled
option:
Regex r = new Regex(@"\d+", RegexOptions.Compiled);
... 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 explicitement Pattern#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 )