import java.util.regex.Pattern;
import java.util.regex.Matcher;Java Regular Expressions: Pattern and Matcher for Text Processing
Direct Answer & Core Concept
Regular expressions, commonly called regex, provide a powerful way to search, validate, extract, split, and replace text based on patterns. Java includes built-in regular expression support through the java.util.regex package.
The two most important classes are Pattern and Matcher. Pattern represents a compiled regular expression, while Matcher applies that pattern to a particular text string.
Whether you need to validate an email address, find numbers inside a sentence, extract hashtags, check a password format, or replace unwanted characters, Java regex can make text processing much easier.
Detailed Explanation & Mechanics
What Are Regular Expressions in Java?
A regular expression is a sequence of characters that describes a text pattern. Instead of checking every character manually, you define what the desired text should look like.
For example, the regex \\d+ means "one or more digits." It can find values such as 123, 45, or 2026 inside larger text.
Java regular expressions are especially useful when the text follows a recognizable structure.
Common Uses of Regex
Regular expressions are commonly used for:
Email and phone-number validation
Username and password rules
Searching text
Extracting numbers or words
Replacing unwanted characters
Checking input formats
Splitting text
Finding repeated patterns
Basic data cleaning
Java Regular Expression Package
Java provides regex functionality through the java.util.regex package.
The two primary classes are:
| Class | Purpose |
|---|---|
Pattern | Compiles a regular expression |
Matcher | Searches or matches text using a Pattern |
Import them with:
For simple operations, Java's String class also provides methods such as matches(), replaceAll(), and split() that internally use regular-expression functionality.
Understanding the Pattern Class
The Pattern class represents a compiled regular expression.
You normally create a Pattern using:
Pattern.compile("regex");Example:
import java.util.regex.Pattern;
public class Main {
public static void main(String[] args) {
Pattern pattern = Pattern.compile("\\d+");
System.out.println(pattern);
}
}Here:
\\d+means one or more digits.
Why Compile a Pattern?
A compiled Pattern can be reused against multiple input strings.
Pattern pattern = Pattern.compile("\\d+");
Matcher first = pattern.matcher("Order 123");
Matcher second = pattern.matcher("Order 456");This is useful when the same regular expression must be applied repeatedly.
Understanding the Matcher Class
The Matcher class performs matching operations against a specific character sequence.
You create a matcher from a pattern:
Matcher matcher = pattern.matcher(text);Example:
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class Main {
public static void main(String[] args) {
Pattern pattern = Pattern.compile("\\d+");
Matcher matcher = pattern.matcher("Order number is 123");
if (matcher.find()) {
System.out.println("Number found");
}
}
}The important difference is:
Patterndescribes what to search for.Matcherworks with where to search.
Pattern Matching with matches()
The matches() method checks whether the entire input matches the regular expression.
Pattern pattern = Pattern.compile("\\d+");
Matcher matcher = pattern.matcher("12345");
System.out.println(matcher.matches());Output:
trueBut:
Matcher matcher = pattern.matcher("Order 12345");
System.out.println(matcher.matches());Output:
falseThe entire string is not made only of digits.
Important Difference
matches() asks:
Does the complete input match this pattern?
find() asks:
Can I find a matching portion somewhere inside the input?
Finding Text with find()
The find() method searches for the next matching portion of the input.
Pattern pattern = Pattern.compile("\\d+");
Matcher matcher = pattern.matcher("Products: 25, 50 and 100");
while (matcher.find()) {
System.out.println(matcher.group());
}Output:
2550100This is one of the most useful regex techniques for extracting information from text.
Getting the Matched Text with group()
After a successful match, group() returns the text that matched the pattern.
Pattern pattern = Pattern.compile("\\d+");
Matcher matcher = pattern.matcher("Price: 499");
if (matcher.find()) {
System.out.println(matcher.group());
}Output:
499You can also use:
matcher.group(0);group(0) represents the complete match.
Getting Match Positions with start() and end()
The start() method returns the starting index of a match.
The end() method returns the index immediately after the matched text.
Pattern pattern = Pattern.compile("\\d+");
Matcher matcher = pattern.matcher("Price: 499");
if (matcher.find()) {
System.out.println("Match: " + matcher.group());
System.out.println("Start: " + matcher.start());
System.out.println("End: " + matcher.end());
}For the string:
Price: 499the output will identify the position where 499 occurs.
Remember that end() is exclusive.
Common Regex Metacharacters
Regular expressions use special characters to describe patterns.
| Regex | Meaning | |
|---|---|---|
. | Any character except line terminators by default | |
^ | Beginning of input | |
$ | End of input | |
* | Zero or more | |
+ | One or more | |
? | Zero or one | |
{n} | Exactly n occurrences | |
{n,m} | Between n and m occurrences | |
[] | Character class | |
() | Capturing group | |
| ` | ` | OR |
\d | Digit | |
\D | Non-digit | |
\s | Whitespace | |
\S | Non-whitespace | |
\w | Word character | |
\W | Non-word character |
Java String Escaping in Regular Expressions
One of the most confusing parts of Java regex is the use of backslashes.
Java strings use \ as an escape character, and regular expressions also use \ for special sequences.
Therefore, a regex such as:
\d+is usually written in Java as:
"\\d+"For example:
Pattern pattern = Pattern.compile("\\d+");Here:
Java processes
\\into a single backslash.The regex engine receives
\d+.
Example
String regex = "\\d{
4
}
";This means:
Match exactly four digits.
It can match:
202612349876Character Classes
Character classes let you specify which characters are allowed.
For example:
[abc]matches one character that is either a, b, or c.
Pattern pattern = Pattern.compile("[abc]+");
Matcher matcher = pattern.matcher("abcab");
System.out.println(matcher.matches());Output:
trueYou can also define ranges.
[a-z]means lowercase letters from a through z.
[A-Z]means uppercase letters.
[0-9]means digits.
Using the Dot Character
The dot . represents a character in most ordinary situations.
Pattern pattern = Pattern.compile("c.t");
Matcher matcher = pattern.matcher("cat");
System.out.println(matcher.matches());Output:
trueThe same pattern can match:
catcotcutc9tbecause the middle character can vary.
Quantifiers in Java Regex
Quantifiers specify how many times a pattern can occur.
* — Zero or More
a*can match:
"""a""aa""aaa"+ — One or More
a+requires at least one a.
? — Zero or One
colou?rcan match:
colorcolour{n} — Exact Number
\d {
4
}matches exactly four digits.
{n,m} — Range
\d {
2,4
}matches between two and four digits.
Greedy and Reluctant Quantifiers
Java regex quantifiers are generally greedy by default. A greedy quantifier attempts to consume as much text as possible while still allowing the overall pattern to match.
For example:
Pattern pattern = Pattern.compile("<.*>");
Matcher matcher = pattern.matcher("<b>Hello</b>");
if (matcher.find()) {
System.out.println(matcher.group());
}The .* portion can consume a large part of the input.
A reluctant quantifier adds ?:
.*?This asks the regex engine to consume as little as possible while still allowing the pattern to match.
For example:
Pattern pattern = Pattern.compile("<.*?>");
Matcher matcher = pattern.matcher("<b>Hello</b>");
while (matcher.find()) {
System.out.println(matcher.group());
}This can identify the individual tag-like portions:
<b></b>Regex should not be treated as a complete HTML parser, but this example demonstrates greedy versus reluctant matching.
Capturing Groups
Parentheses create capturing groups.
Consider:
Pattern pattern = Pattern.compile("(\\d{
4
}
)-(\\d{
2
}
)-(\\d{
2
}
)");This can match:
2026-10-03The groups represent:
Group 1 → 2026Group 2 → 10Group 3 → 03Example:
String text = "Date: 2026-10-03";
Pattern pattern = Pattern.compile("(\\d{4})-(\\d{2})-(\\d{2})");
Matcher matcher = pattern.matcher(text);
if (matcher.find()) {
System.out.println("Year: " + matcher.group(1));
System.out.println("Month: " + matcher.group(2));
System.out.println("Day: " + matcher.group(3));
}Output:
Year: 2026Month: 10Day: 03Named Capturing Groups
Java also supports named capturing groups.
The syntax is:
(?<name>pattern)Example:
String text = "John,25";
Pattern pattern = Pattern.compile( "(?<name>[A-Za-z]+),(?<age>\\d+)");
Matcher matcher = pattern.matcher(text);
if (matcher.find()) {
System.out.println(matcher.group("name"));
System.out.println(matcher.group("age"));
}Output:
John25Named groups can make complex regular expressions easier to understand.
OR Operator in Regular Expressions
The | operator means OR.
For example:
cat|dogmatches either:
cator:
dogJava example:
Pattern pattern = Pattern.compile("cat|dog");
Matcher matcher = pattern.matcher("I have a dog");
if (matcher.find()) {
System.out.println(matcher.group());
}Output:
dogParentheses are useful when applying an operator to multiple alternatives.
(cat|dog)scan match:
catsdogsChecking an Email Address with Regex
A simple email validation pattern can be written as:
String regex = "^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+$";
String email = "user@example.com";
boolean valid = Pattern.matches(regex, email);
System.out.println(valid);Output:
trueThis demonstrates basic structural validation.
However, email syntax has many edge cases, so a simple regex should not be treated as a complete implementation of every valid email standard.
Validating a Phone Number
Suppose your application expects exactly 10 digits:
String regex = "\\d{10}";
String phone = "9876543210";
System.out.println(Pattern.matches(regex, phone));Output:
trueA value such as:
98765will not match.
If your application accepts country codes, spaces, brackets, or hyphens, the regex needs to reflect those requirements.
Extracting Numbers from Text
Regex is useful when numbers are mixed with ordinary text.
String text = "There are 25 apples and 10 oranges.";
Pattern pattern = Pattern.compile("\\d+");
Matcher matcher = pattern.matcher(text);
while (matcher.find()) {
System.out.println(matcher.group());
}Output:
2510This technique is useful for extracting IDs, quantities, years, prices, and other numeric values.
Extracting Words
You can use \\w+ to find word-like sequences.
String text = "Java makes text processing easier.";
Pattern pattern = Pattern.compile("\\w+");
Matcher matcher = pattern.matcher(text);
while (matcher.find()) {
System.out.println(matcher.group());
}This finds sequences of word characters.
For natural-language text, remember that \w is not necessarily equivalent to "every possible human-language word." For internationalized text, choose your pattern and flags carefully.
Replacing Text with Regex
The Matcher class provides replacement methods such as:
replaceAll()replaceFirst()Example:
String text = "Java 123 is powerful 456";
Pattern pattern = Pattern.compile("\\d+");
Matcher matcher = pattern.matcher(text);
String result = matcher.replaceAll("#");
System.out.println(result);Output:
Java # is powerful #Replacing Only the First Match
Use replaceFirst() when only the first matching portion should be replaced.
String text = "Java 123 and 456";
Pattern pattern = Pattern.compile("\\d+");
Matcher matcher = pattern.matcher(text);
String result = matcher.replaceFirst("#");
System.out.println(result);Output:
Java # and 456This is useful when you need targeted replacement instead of replacing every occurrence.
Splitting Text with Regular Expressions
The String.split() method can accept a regular expression.
For example:
String text = "Java,Python;PHP|C++";
String[] languages = text.split("[,;|]");
for (String language : languages) {
System.out.println(language);
}Output:
JavaPythonPHPC++The character class:
[,;
|]means a comma, semicolon, or pipe character can act as a separator.
Using Pattern.matches()
For a simple complete-string check, you don't always need to create a Matcher manually.
You can use:
Pattern.matches(regex, input);Example:
String regex = "\\d+";
String value = "12345";
boolean result = Pattern.matches(regex, value);
System.out.println(result);Output:
trueThis is convenient for one-off checks.
When repeatedly applying the same regex, explicitly compiling and reusing a Pattern can be more appropriate.
Regex Flags
Java supports flags that modify matching behavior.
One common flag is:
Pattern.CASE_INSENSITIVEExample:
Pattern pattern = Pattern.compile( "java", Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher("JAVA");
System.out.println(matcher.find());Output:
trueOther useful flags include:
| Flag | Purpose |
|---|---|
CASE_INSENSITIVE | Ignore case differences |
MULTILINE | Change behavior of ^ and $ for lines |
DOTALL | Allow . to match line terminators |
COMMENTS | Allow whitespace/comments in patterns |
UNICODE_CASE | Unicode-aware case folding with case-insensitive matching |
UNICODE_CHARACTER_CLASS | Enables Unicode-aware predefined character classes |
Flags can also be combined.
Pattern pattern = Pattern.compile( "^java$", Pattern.CASE_INSENSITIVE);Anchors: ^ and $
Anchors define positions rather than consuming characters.
^ represents the beginning of the input, while $ represents the end of the input.
Example:
String regex = "^Java$";
System.out.println(Pattern.matches(regex, "Java"));Output:
trueBut:
Java programmingdoes not match because the complete input is not exactly Java.
With MULTILINE, the behavior of these anchors changes so they can operate relative to individual lines.
Using Matcher.find() in a Loop
When searching for multiple matches, find() is commonly used in a loop.
String text = "ID: 100, ID: 200, ID: 300";
Pattern pattern = Pattern.compile("\\d+");
Matcher matcher = pattern.matcher(text);
while (matcher.find()) {
System.out.println( "Found " + matcher.group() + " at " + matcher.start());
}This approach lets you retrieve both the matching text and its location.
Reusing a Pattern
If the same regex is used repeatedly, compile it once.
Pattern numberPattern = Pattern.compile("\\d+");
String[] values = {
"Order 100", "Order 200", "Order 300"
};
for (String value : values) {
Matcher matcher = numberPattern.matcher(value);
if (matcher.find()) {
System.out.println(matcher.group());
}
}The same Pattern is reused for multiple input strings.
This separates the reusable pattern definition from the individual input being searched.
Pattern and Matcher: Important Difference
A common beginner mistake is treating Pattern and Matcher as the same thing.
They have different responsibilities.
| Feature | Pattern | Matcher |
|---|---|---|
| Represents regex | Yes | No |
| Represents input text | No | Yes |
| Compiles regex | Yes | No |
| Searches input | No | Yes |
find() | No | Yes |
matches() | No | Yes |
group() | No | Yes |
start() | No | Yes |
end() | No | Yes |
Think of it this way:
Pattern → What am I looking for?Matcher → Where am I looking?Complete Java Regex Example
The following example extracts all email-like strings from a sentence:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Main {
public static void main(String[] args) {
String text = """
Contact john@example.com
or support@example.org
for help.
""";
String regex = "[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(text);
while (matcher.find()) {
System.out.println("Email: " + matcher.group());
}
}
}Possible output:
Email: john@example.comEmail: support@example.orgThis example demonstrates the standard Java regex workflow:
1. Create the regex2. Compile it into Pattern3. Create Matcher for input4. Search with find()5. Retrieve matches with group()Common Java Regex Mistakes
1. Forgetting Java String Escaping
Incorrect:
Pattern.compile("\d+");Correct:
Pattern.compile("\\d+");Java requires the backslash to be escaped inside a normal string literal.
2. Confusing matches() with find()
This:
matcher.matches();checks the entire input.
This:
matcher.find();searches for a matching section.
Choosing the wrong method is one of the most common regex bugs.
3. Assuming Regex Validates Everything
A regex can validate a defined structure, but complicated real-world formats can have many edge cases.
For example, email validation, URLs, dates, and international phone numbers can become surprisingly complex.
Use regex for the structural rules your application actually needs.
4. Creating Extremely Complicated Regex
A huge regular expression may technically work but become difficult to maintain.
Prefer several clear validation steps when the business rule is complex.
Readable code is usually easier to test and modify.
5. Ignoring Performance
Some poorly designed regex patterns can cause excessive backtracking on certain inputs.
Be especially careful with nested or overlapping quantifiers such as:
(a+)+For patterns processing large or untrusted input, test performance and avoid unnecessarily ambiguous expressions.
Java Regex Best Practices
Compile Reusable Patterns
If the same regex is used repeatedly, keep a reusable Pattern.
Use Descriptive Regex Variables
Instead of:
String r = "\\d+";prefer:
String numberRegex = "\\d+";This makes the code easier to understand.
Prefer Simple Patterns
Do not create an extremely complicated regex when several straightforward checks would be clearer.
Test Edge Cases
Test empty strings, unexpected characters, Unicode text, long input, and boundary cases.
Be Careful with User Input
Regex applied to untrusted and very large input should be designed with performance in mind.
Use Existing APIs When They Are Better
Regex is powerful, but it is not always the best tool. For structured data such as JSON, XML, or HTML, dedicated parsers are generally preferable.
Regex Cheat Sheet for Java
| Pattern | Meaning | Example | ||
|---|---|---|---|---|
\\d | Digit | 5 | ||
\\d+ | One or more digits | 123 | ||
\\d{4} | Exactly four digits | 2026 | ||
\\s | Whitespace | space | ||
\\w | Word character | A | ||
[A-Z] | Uppercase letter | J | ||
[a-z] | Lowercase letter | a | ||
[0-9] | Digit | 8 | ||
. | Any character in normal mode | a | ||
^ | Start position | beginning | ||
$ | End position | ending | ||
* | Zero or more | aaa | ||
+ | One or more | aaa | ||
? | Zero or one | a | ||
{2,4} | 2 to 4 occurrences | 123 | ||
| ` | ` | OR | `cat | dog` |
() | Capturing group | (\\d+) |
When Should You Use Pattern and Matcher?
Use Pattern and Matcher when you need more control over regular-expression processing.
They are especially useful for:
Extracting multiple matches
Accessing capture groups
Finding match positions
Reusing compiled patterns
Applying regex flags
Performing controlled replacements
Processing large amounts of structured text
For a simple one-time check, Pattern.matches() or String.matches() may be enough.
Java Regular Expressions vs String Methods
Not every text-processing problem requires regex.
For simple exact operations, normal String methods can be easier:
text.contains("Java");
text.startsWith("Java");
text.endsWith("Java");
text.replace("Java", "Python");Regex becomes more useful when the pattern itself is variable.
For example:
\\d+can locate any sequence of digits without knowing the actual number beforehand.
Frequently Asked Questions
What is regex in Java?
Regex, or regular expression, is a pattern language used to search, validate, extract, split, and replace text. Java provides regex support mainly through Pattern and Matcher.
What is the difference between Pattern and Matcher?
Pattern represents a compiled regular expression. Matcher applies that pattern to a specific input sequence and provides operations such as find(), matches(), group(), start(), and end().
What does find() do in Java regex?
find() searches the input for the next portion that matches the pattern. It can be called repeatedly to find multiple matches.
What does matches() do?
matches() attempts to match the entire input against the regular expression.
Why do I write \\d instead of \d in Java?
Because the Java string literal needs the backslash escaped. The regex engine ultimately receives \d.
How do I extract multiple matches?
Use Matcher.find() inside a loop and retrieve each match with matcher.group().
Can Java regex extract numbers?
Yes. A pattern such as:
\\d+can locate sequences of digits in text.
Can Java regex validate email addresses?
Yes, regex can validate a defined email-like structure. However, a simple pattern should not be assumed to cover every valid email address according to all email standards.
Is Pattern thread-safe?
Pattern instances are designed to be immutable and can be safely shared. Matcher instances maintain matching state and should generally be created separately for separate matching operations.
Is regex good for parsing HTML?
Regex can find simple text patterns, but HTML has nested and contextual structure. A dedicated HTML parser is generally more appropriate for reliably parsing HTML documents.
Graphics and Design Ideas
Graphic 1 — Pattern vs Matcher
Create a simple two-column diagram:
┌────────────────────┐ ┌────────────────────┐
│ Pattern │ │ Matcher │
├────────────────────┤ ├────────────────────┤
│ Compiled regex │ ───→ │ Searches text │
│ "\\d+" │ │ "Order 123" │
└────────────────────┘ └────────────────────┘Graphic 2 — Regex Processing Flow
Regex↓Pattern.compile()↓Pattern↓pattern.matcher(text)↓Matcher↓find() / matches()↓group()Graphic 3 — Regex Cheat Sheet
Design a compact visual containing:
\d Digit\s Whitespace\w Word character+ One or more* Zero or more? Optional[] Character class() Capturing group^ Start$ End| ORGraphic 4 — Find Multiple Matches
Show:
Input:"Order 100, Order 200, Order 300"↓Regex:\d+↓Matches:100200300These graphics can be used as custom illustrations or featured images for a Java regular-expression tutorial page.
Runnable Code Example: Java Regular Expressions
Java 17+import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class RegexDemo {
private static final Pattern EMAIL_PATTERN = Pattern.compile("^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,6}$");
public static boolean isValidEmail(String email) {
if (email == null) return false;
return EMAIL_PATTERN.matcher(email).matches();
} public static void main(String[] args) {
System.out.println("Valid email: " + isValidEmail("user@example.com"));
// true
System.out.println("Invalid email: " + isValidEmail("user_at_example"));
// false
}
}