Java Matcher Class
Last modified: April 20, 2025
The java.util.regex.Matcher class is used to perform match operations
on character sequences using patterns. It interprets a compiled regex pattern
against input text to find matches. Matcher objects are not thread-safe.
Matcher provides methods to perform various matching operations, examine match results, and modify input text. It works in conjunction with the Pattern class to provide full regex functionality in Java applications.
Matcher Class Overview
Matcher is created by calling Pattern.matcher with an input
sequence. It maintains state about the current match position and provides
methods to query and manipulate matches. The class supports both simple and
complex matching scenarios.
Key methods include matches, find,
group, and various replacement methods. Matcher also supports
named capturing groups and region limiting for partial matching.
Basic Matching Operations
The Matcher class provides three fundamental matching methods:
matches, lookingAt, and find. Each
serves a different purpose in pattern matching operations.
package com.zetcode;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MatcherBasic {
public static void main(String[] args) {
String input = "The quick brown fox jumps over the lazy dog";
Pattern pattern = Pattern.compile("quick.*fox");
Matcher matcher = pattern.matcher(input);
// matches() - entire input must match
System.out.println("matches(): " + matcher.matches());
// lookingAt() - input must match from beginning
System.out.println("lookingAt(): " + matcher.lookingAt());
// find() - match anywhere in input
System.out.println("find(): " + matcher.find());
// Reset matcher to start from beginning
matcher.reset();
// Find all matches
System.out.println("\nAll matches:");
while (matcher.find()) {
System.out.println("Found at: " + matcher.start() + "-" + matcher.end());
}
}
}
This example demonstrates the three basic matching methods. matches
checks if the entire input matches the pattern. lookingAt checks
if the input starts with the pattern. find searches for the
pattern anywhere in the input.
The example also shows how to use start and end to
get match positions. reset repositions the matcher to the
beginning of the input for repeated searches.
Group Capturing
Matcher supports capturing groups defined by parentheses in the regex pattern. Groups allow extracting specific portions of matched text. Group 0 represents the entire match, while groups 1+ represent captured subpatterns.
package com.zetcode;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MatcherGroups {
public static void main(String[] args) {
String input = "John Doe, age 30, email: john.doe@example.com";
Pattern pattern = Pattern.compile(
"(\\w+ \\w+), age (\\d+), email: (\\S+@\\S+)");
Matcher matcher = pattern.matcher(input);
if (matcher.find()) {
System.out.println("Full match: " + matcher.group(0));
System.out.println("Name: " + matcher.group(1));
System.out.println("Age: " + matcher.group(2));
System.out.println("Email: " + matcher.group(3));
System.out.println("\nGroup count: " + matcher.groupCount());
}
}
}
This example extracts name, age, and email from an input string using capturing groups. The pattern defines three groups enclosed in parentheses. After a successful match, each group's content can be retrieved by its index.
groupCount returns the number of capturing groups in the pattern
(excluding group 0). Groups are numbered from left to right based on their
opening parentheses.
Named Capturing Groups
Java 7 introduced named capturing groups using the (?<name>...)
syntax. Named groups make patterns more readable and matches easier to process.
Group names can be used instead of numerical indices.
package com.zetcode;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MatcherNamedGroups {
public static void main(String[] args) {
String input = "Date: 2023-05-15, Time: 14:30";
Pattern pattern = Pattern.compile(
"Date: (?<date>\\d{4}-\\d{2}-\\d{2}), Time: (?<time>\\d{2}:\\d{2})");
Matcher matcher = pattern.matcher(input);
if (matcher.find()) {
System.out.println("Date: " + matcher.group("date"));
System.out.println("Time: " + matcher.group("time"));
// Still accessible by index
System.out.println("\nGroup 1: " + matcher.group(1));
System.out.println("Group 2: " + matcher.group(2));
}
}
}
This example demonstrates named group capturing. The pattern defines two named groups: "date" and "time". These names make the code more readable and maintainable compared to numerical group references.
Named groups are still accessible by their numerical indices, maintaining backward compatibility. The group naming syntax helps document the pattern's structure within the regex itself.
Text Replacement
Matcher provides powerful text replacement capabilities through
replaceAll and replaceFirst methods. These methods
allow transforming matched text using literal strings or group references.
package com.zetcode;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MatcherReplace {
public static void main(String[] args) {
String input = "User: john_doe, Email: john@example.com";
Pattern pattern = Pattern.compile("(\\w+)@(\\w+\\.\\w+)");
Matcher matcher = pattern.matcher(input);
// Replace first match
String firstReplaced = matcher.replaceFirst("EMAIL_REDACTED");
System.out.println("First replaced: " + firstReplaced);
// Replace all matches
String allReplaced = matcher.replaceAll("$1@DOMAIN.REDACTED");
System.out.println("All replaced: " + allReplaced);
// Append replacement using appendReplacement/appendTail
matcher.reset();
StringBuffer sb = new StringBuffer();
while (matcher.find()) {
matcher.appendReplacement(sb, matcher.group(1) + "@NEW.DOMAIN");
}
matcher.appendTail(sb);
System.out.println("Custom replacement: " + sb.toString());
}
}
This example shows three replacement techniques. replaceFirst
replaces only the first match, while replaceAll replaces all
matches. The dollar-sign notation ($1) references captured groups.
For more complex replacements, appendReplacement and
appendTail provide fine-grained control. These methods allow
processing matches individually while building the result incrementally.
Region Operations
Matcher supports region limiting to restrict matching to a portion of the input.
The region method defines the bounds for matching operations,
while useAnchoringBounds and useTransparentBounds
control boundary behavior.
package com.zetcode;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MatcherRegion {
public static void main(String[] args) {
String input = "Start: 123 Middle: 456 End: 789";
Pattern pattern = Pattern.compile("\\d+");
Matcher matcher = pattern.matcher(input);
// Set region from index 10 to 25
matcher.region(10, 25);
System.out.println("Region matches:");
while (matcher.find()) {
System.out.println("Found: " + matcher.group() +
" at " + matcher.start());
}
// Check anchoring bounds behavior
matcher.region(15, 25);
matcher.useAnchoringBounds(false);
System.out.println("\nWithout anchoring bounds:");
System.out.println("^ matches: " + matcher.hitEnd());
}
}
This example demonstrates region operations. The first part limits matching to characters 10-25 of the input, effectively skipping "Start: 123" and "End: 789". Only numbers within the specified region are found.
The second part shows how anchoring bounds affect pattern matching. When disabled,
the ^ and $ anchors won't match at region boundaries. hitEnd
indicates if matching hit the end of the input region.
Pattern Matching with Flags
Matcher inherits pattern flags from its Pattern object but can override some
behavior. The useCaseInsensitive method enables case-insensitive
matching without recreating the matcher.
package com.zetcode;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MatcherFlags {
public static void main(String[] args) {
String input = "The Quick BROWN fox JUMPS over the lazy DOG";
Pattern pattern = Pattern.compile("\\b[a-z]+\\b");
Matcher matcher = pattern.matcher(input);
System.out.println("Default matching (case sensitive):");
while (matcher.find()) {
System.out.println(matcher.group());
}
// Enable case-insensitive matching
matcher.reset();
matcher.useCaseInsensitive(true);
System.out.println("\nCase-insensitive matching:");
while (matcher.find()) {
System.out.println(matcher.group());
}
}
}
This example shows how to modify matching behavior after matcher creation. The first pass uses case-sensitive matching, finding only lowercase words. After enabling case-insensitive mode, all words are matched regardless of case.
reset clears the matcher's state before reusing it with new
flags. This approach is more efficient than creating a new matcher when only
flags need to change.
Source
Java Matcher Class Documentation
This tutorial has covered the essential methods and features of the Java Matcher class. Mastering these concepts is crucial for effective text processing with regular expressions in Java applications.
Author
List all Java tutorials.