The compile()
method is always called at some point; it's the only way to create a Pattern object. So the question is really, why should you call it explicitly? One reason is that you need a reference to the Matcher object so you can use its methods, like group(int)
to retrieve the contents of capturing groups. The only way to get hold of the Matcher object is through the Pattern object's matcher()
method, and the only to get hold of the Pattern object is through the compile()
method. Then there's the find()
method which, unlike matches()
, is not duplicated in the String or Pattern classes.
The other reason is to avoid creating the same Pattern object over and over. Every time you use one of the regex-powered methods in String (or the static matches()
method in Pattern), it creates a new Pattern and a new Matcher. So this code snippet:
for (String s : myStringList) {
if ( s.matches("\\d+") ) {
doSomething();
}
}
...is exactly equivalent to this:
for (String s : myStringList) {
if ( Pattern.compile("\\d+").matcher(s).matches() ) {
doSomething();
}
}
Obviously, that's doing a lot of unnecessary work. In fact, it can easily take longer to compile the regex and instantiate the Pattern object, than it does to perform an actual match. So it usually makes sense to pull that step out of the loop. You can create the Matcher ahead of time as well, though they're not nearly so expensive:
Pattern p = Pattern.compile("\\d+");
Matcher m = p.matcher("");
for (String s : myStringList) {
if ( m.reset(s).matches() ) {
doSomething();
}
}
If you're familiar with .NET regexes, you may be wondering if Java's compile()
method is related to .NET's RegexOptions.Compiled
modifier; the answer is no. In .NET you don't usually have to worry about redundant object creation because the system automatically caches a certain number of Regex objects, whether you use a constructor or one of the static convenience methods like Regex.Matches(s, @"\d+")
. If you specify the Compiled
option:
Regex r = new Regex(@"\d+", RegexOptions.Compiled);
...it compiles the regex directly to CIL byte code, allowing it to perform much faster, but at a significant cost in up-front processing and memory use--think of it as steroids for regexes. Java has no equivalent for .NET's Compiled
option. There's no difference between a Pattern that's created behind the scenes by String#matches(String)
and one you create explicitly with Pattern#compile(String)
.