Regular expressions (regex) let you describe patterns in text. Java’s java.util.regex package provides Pattern and Matcher for powerful, reusable pattern matching.
Quick Start
String email = "alice@example.com";
boolean valid = email.matches("[\\w.+-]+@[\\w-]+\\.[a-zA-Z]{2,}");
System.out.println(valid); // true
Core Classes
Pattern — Compiled Regex
import java.util.regex.Pattern;
import java.util.regex.Matcher;
Pattern pattern = Pattern.compile("\\d+"); // one or more digits
Compile once, reuse many times — much faster than calling String.matches() repeatedly.
Matcher — Applying a Pattern
Matcher matcher = pattern.matcher("Order 42, Item 7");
while (matcher.find()) {
System.out.println("Found: " + matcher.group());
}
// Found: 42
// Found: 7
Regex Syntax Reference
Character Classes
| Pattern |
Matches |
. |
Any character (except newline) |
\d |
Digit [0-9]
|
\D |
Non-digit |
\w |
Word character [a-zA-Z0-9_]
|
\W |
Non-word character |
\s |
Whitespace [ \t\n\r\f]
|
\S |
Non-whitespace |
[abc] |
a, b, or c |
[^abc] |
Not a, b, or c |
[a-z] |
Lowercase letter |
Quantifiers
| Quantifier |
Meaning |
* |
0 or more |
+ |
1 or more |
? |
0 or 1 (optional) |
{n} |
Exactly n |
{n,} |
n or more |
{n,m} |
Between n and m |
Anchors
| Anchor |
Meaning |
^ |
Start of string |
$ |
End of string |
\b |
Word boundary |
String Regex Methods
String s = "Hello 123 World 456";
// matches() — must match ENTIRE string
s.matches(".*\\d+.*") // true
// replaceAll() — replace all matches
s.replaceAll("\\d+", "#") // "Hello # World #"
// replaceFirst() — replace first match
s.replaceFirst("\\d+", "#") // "Hello # World 456"
// split() — split by regex
"one:two::three".split(":") // ["one", "two", "", "three"]
"one:two::three".split(":+") // ["one", "two", "three"]
Groups and Capturing
Parentheses create capturing groups:
Pattern p = Pattern.compile("(\\w+)@(\\w+)\\.(\\w+)");
Matcher m = p.matcher("alice@example.com");
if (m.matches()) {
System.out.println("Full: " + m.group(0)); // alice@example.com
System.out.println("User: " + m.group(1)); // alice
System.out.println("Domain: " + m.group(2)); // example
System.out.println("TLD: " + m.group(3)); // com
}
Named Groups (Java 7+)
Pattern p = Pattern.compile("(?<user>\\w+)@(?<domain>\\w+\\.\\w+)");
Matcher m = p.matcher("alice@example.com");
if (m.matches()) {
System.out.println(m.group("user")); // alice
System.out.println(m.group("domain")); // example.com
}
Common Patterns
Email (Basic)
String emailRegex = "[\\w.+-]+@[\\w-]+\\.[a-zA-Z]{2,}";
Phone Number (US)
String phoneRegex = "\\(?\\d{3}\\)?[-.\\s]?\\d{3}[-.\\s]?\\d{4}";
// Matches: (123) 456-7890, 123-456-7890, 123.456.7890
URL
String urlRegex = "https?://[\\w.-]+(?:/[\\w./-]*)?";
IP Address (IPv4)
String ipRegex = "\\b(?:\\d{1,3}\\.){3}\\d{1,3}\\b";
Date (YYYY-MM-DD)
String dateRegex = "\\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\\d|3[01])";
Practical Examples
String text = "Visit https://example.com or http://docs.java.net/api for info.";
Pattern p = Pattern.compile("https?://[\\w.-]+(?:/[\\w./-]*)?");
Matcher m = p.matcher(text);
while (m.find()) {
System.out.println(m.group());
}
// https://example.com
// http://docs.java.net/api
Validate and Parse CSV Line
String line = "Alice,30,\"New York\"";
Pattern p = Pattern.compile("\"([^\"]*)\"|([^,]+)");
Matcher m = p.matcher(line);
while (m.find()) {
String value = m.group(1) != null ? m.group(1) : m.group(2);
System.out.println(value);
}
// Alice
// 30
// New York
Word Frequency Counter
String text = "the cat sat on the mat the cat";
Pattern word = Pattern.compile("\\b\\w+\\b");
Matcher m = word.matcher(text.toLowerCase());
Map<String, Integer> freq = new HashMap<>();
while (m.find()) {
freq.merge(m.group(), 1, Integer::sum);
}
System.out.println(freq);
// {the=3, cat=2, sat=1, on=1, mat=1}
Flags
// Case-insensitive
Pattern p = Pattern.compile("hello", Pattern.CASE_INSENSITIVE);
// Multiple flags
Pattern p2 = Pattern.compile("^start",
Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
// Inline flag
Pattern p3 = Pattern.compile("(?i)hello");
| Flag |
Constant |
Inline |
| Case-insensitive |
CASE_INSENSITIVE |
(?i) |
| Multiline |
MULTILINE |
(?m) |
Dotall (. matches \n) |
DOTALL |
(?s) |
| Comments |
COMMENTS |
(?x) |
-
Compile once, reuse —
Pattern.compile() is expensive. Store the Pattern as a static final field.
-
Avoid catastrophic backtracking — be careful with nested quantifiers like
(a+)+.
-
Use possessive quantifiers (
++, *+) or atomic groups when possible.
-
Prefer
String methods for simple tasks — don’t use regex for contains() or startsWith().
// GOOD — compiled once
private static final Pattern DIGITS = Pattern.compile("\\d+");
public List<String> findNumbers(String text) {
Matcher m = DIGITS.matcher(text);
List<String> results = new ArrayList<>();
while (m.find()) results.add(m.group());
return results;
}
Common Mistakes
| Mistake |
Problem |
Fix |
"\\d" vs "\d"
|
Java strings need double backslash |
Always \\d in Java |
matches() expects full match |
"123abc".matches("\\d+") → false |
Use find() for partial match |
Not reusing Pattern
|
Recompiles every call |
Store as static final
|
| Greedy by default |
.* grabs too much |
Use .*? for lazy |
Key Takeaways
- Use
Pattern.compile() + Matcher for reusable, performant regex.
-
String.matches() checks the entire string; Matcher.find() finds partial matches.
- Use named groups for readable extraction.
- Compile patterns once and store as
static final.
- Don’t use regex when simple
String methods suffice.
What’s Next?
We move into utility classes, starting with Java Enum — type-safe constants with fields, methods, and more.