Regular Expressions in Java

1. What is Regex?

A regular expression (regex) is a sequence of characters that defines a search pattern. Regex engines scan input text and identify portions that match the specified pattern. Java provides built-in regex support through the java.util.regex package, available since JDK 1.4.

Common use cases include:

  • Validation — verify that an email address, phone number, or postal code is correctly formatted.
  • Search — locate one or more occurrences of a pattern within a larger string.
  • Replace — substitute matched substrings with new content.
  • Split — break a string into tokens using a delimiter pattern.
  • Extract — pull out specific data (dates, prices, URLs) from unstructured text.

Note: Java regex syntax is largely compatible with Perl-style regular expressions, which are also used in Python, JavaScript, and most modern languages.

2. Key Classes

The java.util.regex package contains three primary classes:

Class Role
Pattern Compiled representation of a regex. Created via Pattern.compile(regex). Immutable and thread-safe; reuse instances for efficiency.
Matcher Engine that performs match operations on a character sequence using a Pattern. Created via pattern.matcher(input). Not thread-safe; create one per thread.
PatternSyntaxException Unchecked exception thrown when a regex pattern string has a syntax error. Extends IllegalArgumentException.

3. Basic Pattern Matching

The simplest workflow: compile a pattern, create a matcher for the input, then call matches() to test whether the entire input matches the pattern.

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

public class BasicMatch {
    public static void main(String[] args) {
        String pattern = "\\d{3}-\\d{4}";   // e.g. 555-1234
        String input   = "555-1234";

        Pattern p = Pattern.compile(pattern);
        Matcher m = p.matcher(input);

        if (m.matches()) {
            System.out.println("Input matches the pattern.");
        } else {
            System.out.println("No match.");
        }
    }
}
Input matches the pattern.

Warning: matches() requires the entire string to match. Use find() to locate a pattern anywhere within the input.

4. Pattern Class

The Pattern class is the entry point for all regex operations. Its key static and instance methods are:

compile()

Compiles the regex string into a reusable Pattern object. Optionally accepts flags such as Pattern.CASE_INSENSITIVE.

Pattern p = Pattern.compile("[a-z]+", Pattern.CASE_INSENSITIVE);

matcher()

Creates a Matcher bound to the given input string.

Matcher m = p.matcher("Hello World");

matches() — static shortcut

Compiles and matches in one call. Convenient for one-off checks.

boolean ok = Pattern.matches("\\d+", "12345");  // true

split()

Splits the input string around matches of the pattern — similar to String.split() but with a pre-compiled pattern.

Pattern p = Pattern.compile("[,;\\s]+");
String[] tokens = p.split("one, two;  three four");
for (String t : tokens) System.out.println(t);
one
two
three
four

5. Matcher Class

A Matcher performs the actual searching. Key methods:

find()

Advances through the input and returns true each time a new match is found. Ideal for iterating over all occurrences.

Pattern p = Pattern.compile("\\d+");
Matcher m = p.matcher("Order 42, item 7, qty 100");
while (m.find()) {
    System.out.println("Found: " + m.group() + " at index " + m.start());
}
Found: 42 at index 6
Found: 7 at index 15
Found: 100 at index 22

group(), start(), end()

After a successful find() or matches(), these methods return the matched substring, its start index, and its end index respectively.

Pattern p = Pattern.compile("(\\w+)@(\\w+\\.\\w+)");
Matcher m = p.matcher("Contact: alice@example.com today.");
if (m.find()) {
    System.out.println("Full match : " + m.group(0));
    System.out.println("Username   : " + m.group(1));
    System.out.println("Domain     : " + m.group(2));
    System.out.println("Start/End  : " + m.start() + " / " + m.end());
}
Full match : alice@example.com
Username : alice
Domain : example.com
Start/End : 9 / 26

replaceAll()

Replaces every match in the input with the given replacement string.

String result = Pattern.compile("\\bfoo\\b")
                       .matcher("foo foobar foo")
                       .replaceAll("bar");
System.out.println(result);
bar foobar bar

6. Character Classes

Character classes match a single character against a set of allowed characters defined inside square brackets.

Syntax Meaning Example Match
[abc] Any one of a, b, or c "a", "b", "c"
[^abc] Any character except a, b, or c "d", "z"
[a-z] Any lowercase letter a through z "m", "p"
[A-Z] Any uppercase letter A through Z "G", "T"
[0-9] Any digit 0 through 9 "3", "7"
. Any character except newline "x", "@", "5"

7. Predefined Character Classes

Java regex provides shorthand escape sequences for common character groups.

Shorthand Meaning Equivalent
\d Any digit [0-9]
\D Any non-digit [^0-9]
\w Any word character (letter, digit, underscore) [a-zA-Z0-9_]
\W Any non-word character [^a-zA-Z0-9_]
\s Any whitespace (space, tab, newline) [ \t\r\n\f]
\S Any non-whitespace [^ \t\r\n\f]

In Java strings: backslash must be escaped, so write \\d in a Java string literal to represent the regex token \d.

8. Quantifiers

Quantifiers specify how many times a preceding element must occur to constitute a match.

Quantifier Meaning Example Pattern Matches
* 0 or more times go* "g", "go", "goo", "gooo"
+ 1 or more times go+ "go", "goo" (not "g")
? 0 or 1 time (optional) colou?r "color", "colour"
{n} Exactly n times \d{4} "2024", "1999"
{n,} At least n times \d{2,} "12", "999", "10000"
{n,m} Between n and m times \d{2,4} "12", "123", "1234"

By default, quantifiers are greedy — they match as much as possible. Append ? to make them lazy (e.g. .*?) — match as little as possible.

9. Anchors and Boundaries

Anchors do not consume characters; they assert a position in the input string.

Anchor Asserts Example
^ Start of string (or start of line in MULTILINE mode) ^Hello matches "Hello world" but not "Say Hello"
$ End of string (or end of line in MULTILINE mode) world$ matches "Hello world" but not "world peace"
\b Word boundary (between \w and \W) \bcat\b matches "cat" but not "concatenate"
\B Non-word boundary \Bcat\B matches "concatenate" but not standalone "cat"
Pattern p = Pattern.compile("^\\d{4}$");
System.out.println(p.matcher("2024").matches());     // true
System.out.println(p.matcher("20245").matches());    // false
System.out.println(p.matcher("abc").matches());      // false
true
false
false

10. Common Practical Examples

Email Validation

public static boolean isValidEmail(String email) {
    String regex = "^[a-zA-Z0-9._%+\\-]+@[a-zA-Z0-9.\\-]+\\.[a-zA-Z]{2,}$";
    return Pattern.matches(regex, email);
}

System.out.println(isValidEmail("user@example.com"));   // true
System.out.println(isValidEmail("bad-email@"));         // false
System.out.println(isValidEmail("also.bad@.com"));      // false
true
false
false

Phone Number Validation (US format)

public static boolean isValidPhone(String phone) {
    // Accepts: (123) 456-7890, 123-456-7890, 1234567890
    String regex = "^(\\(\\d{3}\\)\\s?|\\d{3}[-.]?)\\d{3}[-.]?\\d{4}$";
    return Pattern.matches(regex, phone);
}

System.out.println(isValidPhone("(800) 555-1234"));   // true
System.out.println(isValidPhone("800-555-1234"));     // true
System.out.println(isValidPhone("8005551234"));       // true
System.out.println(isValidPhone("1234"));             // false
true
true
true
false

URL Pattern Extraction

String text = "Visit https://www.example.com or http://docs.java.net for more.";
Pattern p = Pattern.compile("https?://[\\w./-]+");
Matcher m = p.matcher(text);
while (m.find()) {
    System.out.println("URL: " + m.group());
}
URL: https://www.example.com
URL: http://docs.java.net

11. String Regex Methods

The String class provides convenient regex shortcuts that do not require creating Pattern or Matcher objects explicitly.

matches()

Tests whether the entire string matches the given regex. Equivalent to Pattern.matches(regex, str).

String s = "hello123";
System.out.println(s.matches("[a-z]+\\d+"));   // true
System.out.println(s.matches("[a-z]+"));       // false (digits not covered)
true
false

replaceAll()

Replaces every substring matching the regex with the replacement. Internally creates a new Pattern on each call — cache a Pattern when calling in a loop.

String cleaned = "Hello   World  !".replaceAll("\\s+", " ");
System.out.println(cleaned);
Hello World !

split()

Splits the string at each point where the regex matches, returning a String[].

String csv = "apple, banana,  cherry,date";
String[] fruits = csv.split(",\\s*");
for (String f : fruits) System.out.println(f);
apple
banana
cherry
date

Performance tip: String.replaceAll() and String.split() recompile the pattern on every invocation. If you call them repeatedly with the same pattern, compile it once with Pattern.compile() and reuse it.

Continue learning