library
intermediateRegular Expressions in Java
Use Pattern and Matcher for regex operations and know the performance implications of compiled vs inline patterns.
Pattern compiles a regular expression. Matcher runs it against input.
Compiling a Pattern = building a custom maze. Each Matcher call = running a mouse through the maze. Reusing the maze (Pattern) is fast; rebuilding it every time (String.matches) is slow.
Key Concepts
1
private static final Pattern EMAIL =
Pattern.compile("^[\\w.+-]+@[\\w-]+\\.[\\w.]+$");2
Matcher m = EMAIL.matcher(input);
if (m.matches()) { ... }3
Compile once, into a constant. This is the mistake that matters:
4
for (String s : millionLines)
if (s.matches("\\d+")) { ... } // recompiles every iteration5
String.matches, replaceAll and split all compile the pattern on every call. In a loop that is
hundreds of times slower than a pre-compiled Pattern.
String.matchesreplaceAllsplitPattern
6
matches and find are different questions.
matches() must the WHOLE input match?
find() is there a match anywhere? call again for the next
lookingAt() does the match start at the beginning?matchesfind
7
Capture groups pull pieces out:
Pattern p = Pattern.compile("(\\d{4})-(\\d{2})-(\\d{2})");
Matcher m = p.matcher("2026-03-15");
if (m.matches()) {
m.group(1); // "2026"
m.group(0); // the whole match
}8
Named groups read better once there are more than two:
9
Pattern.compile("(?<year>\\d{4})-(?<month>\\d{2})");
m.group("year");10
The syntax worth memorising.
\d digit \w word char \s whitespace . any char
* zero or more + one or more ? zero or one
{2,5} a range ^ start $ end
[a-z] class [^a-z] negated
(x) capturing (?:x) non-capturing11
Flags go in compile:
Pattern.compile("^abc$", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);compile
12
Threading: Pattern is safe to share, Matcher is not. So a static Pattern field is correct, and a
static Matcher is a race condition.
PatternMatcher
13
Catastrophic backtracking is the production hazard.
Pattern.compile("(a+)+b").matcher("aaaaaaaaaaaaaaaaaaaaaaaaaa!");14
Nested quantifiers make the engine try exponentially many splits, and one request pins a CPU for minutes.
That is a denial of service if the pattern or the input comes from a user.
15
What the interviewer is probing.1. "Why compile a Pattern into a constant?" Probing: the cost people leave in loops. Stalls:
"It is tidier." Moves up: String.matches, replaceAll and split compile the pattern on every call,
which in a loop is orders of magnitude slower than a reused Pattern.
16
2. "Is Matcher thread-safe?" Probing: what can be shared. Stalls: "Yes, like Pattern."
Moves up: Pattern is safe to share; Matcher is not, so a static Matcher is a race condition.
17
3. "What is catastrophic backtracking?" Probing: the production hazard. Stalls: "A slow
regex." Moves up: nested quantifiers like (a+)+b make the engine try exponentially many splits, so
one request pins a CPU for minutes — a denial of service if the input is user-supplied.
18
4. "matches versus find?" Probing: a distinction that silently changes behaviour. Stalls:
"The same." Moves up: matches requires the entire input to match; find looks for a match anywhere
and can be called repeatedly.