Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

Java already supports named capture groups. For most applications, use java.util.regex.Pattern and Matcher; adding a dependency solely to retrieve captures by name solves no problem. Choose an alternative such as RE2/J only when you need its restricted syntax and predictable linear-time matching, or when compatibility with another regex flavor is a documented requirement.

Java named groups in one example

import java.util.regex.Matcher;
import java.util.regex.Pattern;

Pattern email = Pattern.compile(
    "(?<user>[A-Za-z0-9._%+-]+)@(?<domain>[A-Za-z0-9.-]+)"
);

Matcher matcher = email.matcher("[email protected]");
if (matcher.matches()) {
    System.out.println(matcher.group("user"));   // alice
    System.out.println(matcher.group("domain")); // example.com
}

The regex form (?<name>...) captures text and assigns it a symbolic name. Java’s syntax and naming rules are documented in the Pattern API.

Declaration, retrieval and backreferences

Declare a group

(?<year>d{4})-(?<month>d{2})-(?<day>d{2})

In Java source, each regex backslash needs another backslash in the string literal:

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Pattern date = Pattern.compile(
    "(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})"
);

A group name must begin with a letter and may contain letters and digits. The Java documentation does not list underscore as a valid character, so prefer username to user_name.

Read the value and its offsets

if (matcher.find()) {
    String value = matcher.group("domain");
    int start = matcher.start("domain");
    int end = matcher.end("domain");
}
  • group("name") returns the captured text.
  • start("name") and end("name") return character offsets.
  • group() or group(0) returns the complete match.
  • Calling a group accessor before a successful find() or matches() throws an exception.

matches() requires the entire input to match; find() searches for the next matching subsequence. The named accessors are also available through MatchResult.

Named backreferences

Pattern repeated = Pattern.compile("(?<word>\w+)\s+\k<word>");

k<word> requires the same text captured by word. Do not confuse it with replacement syntax, described below.

Names do not remove numeric groups

Named groups are still numbered from left to right; group zero is always the complete match.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Number Name Value for 2026-09
0 — 2026-09
1 date 2026-09
2 year 2026
3 month 09
(?<date>(?<year>d{4})-(?<month>d{2}))

Use names in application code because inserting an earlier capturing parenthesis can shift every later number. Numeric access remains useful for generic tooling.

Optional and repeated captures

Pattern url = Pattern.compile("(?<scheme>https?://)?(?<host>[^/]+ ");
Matcher m = url.matcher("example.com");
if (m.matches()) {
    String scheme = m.group("scheme"); // null
    String host = m.group("host");     // example.com
}

An optional group that did not participate returns null; check it before calling methods such as toLowerCase().

A quantified group stores only the capture from its most recent successful iteration. It is not a collection of captures. To collect every item, match repeatedly:

Pattern tag = Pattern.compile("(?<tag>\w+)");
Matcher tags = tag.matcher("red blue green");
while (tags.find()) {
    list.add(tags.group("tag"));
}

Group names also cannot be reused in one Java pattern.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Named groups in replacements

Pattern backreferences and replacement references use different syntaxes:

  • k<name> is a backreference inside the regex.
  • ${name} refers to a named group in a replacement string.
Pattern person = Pattern.compile("(?<first>\w+)\s+(?<last>\w+)");
String result = person.matcher("Ada Lovelace")
    .replaceAll("${last}, ${first}");
// Lovelace, Ada

See the Matcher documentation for replacement rules.

Modern Java version note

Feature Version guidance
Named declaration and group(String) Available since Java 7-era releases and later
Pattern.namedGroups() Java 20
Java SE 26 API reference Documentation for JDK 26

namedGroups() returns an unmodifiable map from names to group numbers. It is useful for introspection, but it raises the minimum JDK for that code; ordinary named matching does not require Java 20.

Pattern p = Pattern.compile("(?<year>\d{4})-(?<month>\d{2})");
System.out.println(p.namedGroups()); // Java 20+

Is a third-party regex engine better?

Only for a different requirement. Java’s built-in engine provides lookarounds, backreferences, possessive quantifiers, atomic groups and Java’s Unicode options without a deployment change. It is the default for trusted, reviewed patterns and normal parsing, validation and extraction.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

RE2/J: choose safety over full Java syntax

RE2 is designed for predictable, linear-time matching; RE2/J is its pure-Java port. It supports named captures and a familiar API:

<dependency>
  <groupId>com.google.re2j</groupId>
  <artifactId>re2j</artifactId>
  <version>1.8</version>
</dependency>
import com.google.re2j.Matcher;
import com.google.re2j.Pattern;

Pattern p = Pattern.compile("(?<user>[A-Za-z0-9._%+-]+)@(?<domain>[A-Za-z0-9.-]+)");
Matcher m = p.matcher("[email protected]");
if (m.matches()) {
    System.out.println(m.group("user"));
}

Use RE2/J when patterns or inputs may be user-controlled and a restricted regular-expression language is acceptable. It intentionally omits backreferences, lookahead, lookbehind, atomic groups and possessive quantifiers. A Java pattern using those features is not a drop-in migration. RE2’s syntax reference lists supported and unsupported constructs.

Linear-time design is a safety property, not a promise of lower latency for every workload; benchmark representative inputs and retain input-size limits.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

JRegex and Joni: compatibility choices, not upgrades

JRegex uses nonstandard named-group syntax such as ({Name}REGEX). Consider it only when maintaining an existing JRegex codebase, and verify its current Java support and maintenance before deployment.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Joni is an Oniguruma-style engine used in some Ruby/JRuby ecosystems. It can be justified by an existing Ruby-compatible syntax requirement, but it should not be presented as a general replacement for java.util.regex. Test the exact version and constructs you need.

Best Value

Apache Commons Lang is a utility library, not a replacement regex engine.

Feature and decision comparison

Requirement Choice Reason
Named groups, no dependency java.util.regex Built into the JDK
Lookarounds or backreferences java.util.regex RE2/J omits them
User-supplied patterns or hostile input Evaluate RE2/J Restricted syntax and linear-time design
Ruby/Oniguruma compatibility Joni Compatibility may justify the dependency
Legacy JRegex application JRegex Avoid needless migration
Nested or highly structured grammar Parser Regex may be the wrong abstraction
Feature java.util.regex RE2/J
Named capture and retrieval Yes Yes
Lookahead/lookbehind Yes No
Backreferences Yes No
Possessive quantifiers/atomic groups Yes No
General linear-time guarantee No Designed for it
Extra dependency No Yes

Security, portability and testing

Named groups do not make a pattern safe. Backtracking patterns can exhibit excessive work with adversarial input. Bound input length, avoid nested ambiguous quantifiers, impose execution/resource limits where your architecture allows it, and test hostile cases. If the required syntax fits, RE2/J is worth evaluating for untrusted patterns.

Do not assume similar-looking flavors behave identically. Test named syntax ((?<name>...) and, where supported, (?P<name>...)), Unicode classes, word boundaries, case folding, empty matches, replacement syntax and error behavior in the exact engine and version you deploy. Java’s w, b and . should be tested against the languages your application accepts.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

A practical test matrix includes: successful and failed matches; find() versus matches(); absent optional groups; repeated captures; named backreferences; invalid, duplicate or digit-leading names; named replacements; Java escaping; lookarounds and backreferences; large adversarial inputs; and the same corpus run through both engines before migration.

Bottom line

Use java.util.regex for named groups in ordinary Java code. The syntax is stable, the APIs are standard, and no library is needed. Add RE2/J only when predictable behavior on untrusted patterns outweighs Java’s advanced features. Treat JRegex and Joni as narrowly justified compatibility dependencies, not as better ways to name captures.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.