skip to content

Regular Expressions

java.util.regex end to end: the compile-and-match model, character classes, quantifiers, groups, lookaround, anchors, flags, replacement and splitting, and the backtracking performance cliff. Interviewers use regex both for practical parsing and for the ReDoS security angle.

part ofJavaoverview, primer and where to startread it →
on this pageshow

explore

questions

page 2 of 2

How do inline flag groups like (?i:...) work in Java regex, and how do they differ from a leading (?i)? How do you turn a flag off for part of a pattern?

level: seniorimportance: should knowfreq 40%

basics

~20 s

A leading (?i) turns a flag on for the rest of the pattern. The form (?i:...) is a non-capturing group that applies the flag only inside that group. You turn a flag off for a region with (?-i:...).

open as a page

What is a backreference in a Java regex, and what is a common use for one?

level: seniorimportance: should knowfreq 52%

basics

~10 s

A backreference like \1 matches the same text that an earlier capturing group already matched (not the pattern again, the actual text). A common use is finding doubled words, e.g. \b(\w+)\s+\1\b matches 'the the'.

open as a page

What is the bounded-length restriction on lookbehind in Java, and how do you work around an unbounded requirement?

level: seniorimportance: should knowfreq 45%

basics

~20 s

Java's lookbehind must match text of a limited, known maximum length. So (?<=ab) is fine and bounded quantifiers like (?<=a{1,5}) work, but truly unbounded ones like (?<=a+) or (?<=a*) are not allowed because the engine must know how far back to look.

open as a page

Using lookarounds, how would you insert thousands separators into a number string in Java, and why does this work without deleting any digits?

level: seniorimportance: should knowfreq 38%

basics

~20 s

Match the empty positions between digits where exactly a multiple of three digits remain, using (?<=\d)(?=(\d{3})+$), and replace each with a comma. It matches zero-width positions, so no digit is consumed or removed - commas are just inserted.

open as a page

What kind of matching engine does java.util.regex use, and what is catastrophic backtracking?

level: seniorimportance: should knowfreq 55%

basics

~20 s

Java's regex engine is a backtracking NFA, not a DFA. On certain patterns with nested or overlapping repetition it can try an exponential number of paths on a non-matching input, freezing the thread. This is catastrophic backtracking, the cause of regex denial-of-service (ReDoS).

open as a page

What are possessive quantifiers in Java, how do they differ from greedy ones, and what are atomic groups?

level: seniorimportance: should knowfreq 48%

basics

~20 s

A possessive quantifier (written with a trailing +, like a++) grabs as much as it can and then never gives any of it back — it disables backtracking for that part. An atomic group (?>...) does the same thing for a whole subpattern.

open as a page

How do possessive quantifiers and atomic groups prevent catastrophic backtracking in Java?

level: seniorimportance: should knowfreq 40%

basics

~20 s

Possessive quantifiers (a++, a*+) and atomic groups ((?>...)) tell the engine: match as much as you can and never give any of it back. Removing those give-back choice points stops the exponential re-trying that causes the blowup.

open as a page

For high-throughput replacement, when should you use Matcher.replaceAll / appendReplacement instead of String.replaceAll, and why?

level: seniorimportance: should knowfreq 40%

basics

~10 s

String.replaceAll recompiles the regex on every call. In hot paths, compile the pattern once with Pattern.compile and reuse a Matcher (matcher.replaceAll). For replacements computed from each match, use appendReplacement/appendTail or replaceAll with a Function.

open as a page

How can capturing groups and backreferences contribute to catastrophic backtracking (ReDoS), and how do you design Java regexes to avoid it?

level: principalimportance: should knowfreq 34%

basics

~20 s

Java's regex engine backtracks. Ambiguous nested quantifiers and backreferences can make it try exponentially many combinations on certain inputs, freezing a thread (a denial of service). Avoid it with unambiguous patterns, atomic groups, possessive quantifiers, and input limits.

open as a page

What is catastrophic backtracking (ReDoS) in regex, how do quantifiers cause it, and how do you prevent it in a Java service?

level: principalimportance: should knowfreq 40%

basics

~20 s

Catastrophic backtracking happens when nested or overlapping quantifiers give the engine exponentially many ways to match, so a crafted input makes one regex run effectively forever. An attacker can use this to freeze a thread — that's ReDoS. You prevent it with possessive quantifiers, atomic groups, or unambiguous patterns.

open as a page

As a tech lead, how would you detect and prevent ReDoS vulnerabilities across a Java codebase?

level: principalimportance: should knowfreq 30%

basics

~20 s

Find risky patterns with linters and code review, test patterns against malicious inputs, never let users supply patterns to the default engine, and run untrusted matching with a timeout or a linear-time engine like RE2J so no single regex can hang a thread.

open as a page

How can lookahead/lookbehind be used with String.split or Pattern.split to keep delimiters, and what is the trade-off versus a normal split?

level: middleimportance: nice to knowfreq 30%

basics

~20 s

split breaks on the matched delimiter and throws it away. If you split on a zero-width lookaround position instead, no characters are consumed, so the delimiter stays attached to a piece. For example split on (?<=,) keeps the comma at the end of each chunk.

open as a page

What do Matcher.region(), reset(), and matcher reuse let you control, and why is matches() within a region not the same as matching the whole string?

level: seniorimportance: nice to knowfreq 28%

basics

~20 s

region() limits matching to a sub-range of the input so methods like find() and matches() only see that window. reset() clears match state and position so you can search again or swap in new input. Reusing one Matcher avoids creating new objects when scanning sequentially.

open as a page

Anchors are zero-width assertions. How do they relate to lookahead/lookbehind, and how would you build a custom positional assertion in Java?

level: principalimportance: nice to knowfreq 30%

basics

~20 s

Anchors like ^, $, and \b are built-in zero-width assertions that test a fixed position. Lookahead (?=...) and lookbehind (?<=...) are general zero-width assertions you define yourself, letting you build custom 'boundaries' that the standard anchors can't express.

open as a page

showing 31–44 of 44