Regular Expressions in Java

Naveen AnamaneniUpdated · 5 min read

indexOf("411001") finds one exact PIN code. But what if you need to find every six-digit PIN code in an address book, whatever the digits are? You need to describe the shape of the text, "six digits in a row", rather than the exact text. A regular expression (regex for short) is a small language for describing such shapes, and Java's java.util.regex package uses it to search, validate and split text.

Finding Every PIN Code

Compile the pattern once; the matcher finds each match in turn
Pins.java▶ Try it
import java.util.regex.Matcher;
import java.util.regex.Pattern;
 
public class Pins {
    public static void main(String[] args) {
        Pattern pin = Pattern.compile("\\d{6}");
        Matcher m = pin.matcher("Ship to Pune 411001, backup 500081.");
 
        while (m.find()) {
            System.out.println(m.group() + " at " + m.start() + "-" + m.end());
        }
    }
}
Output
411001 at 13-19
500081 at 28-34

How it works

  1. \d{6} means "a digit, exactly 6 times". In a Java string, the backslash itself must be escaped, so you write "\\d{6}".
  2. Pattern.compile turns the pattern text into a Pattern object, ready to use.
  3. pattern.matcher(text) creates a Matcher for one piece of text.
  4. Each find() searches forward from where the last match ended. It returns true and remembers the match, or false when there are no more.
  5. group() is the matched text; start() and end() are its positions (end excluded, like substring).

find, matches and lookingAt

The three ways to apply a pattern answer different questions:

ThreeWays.java▶ Try it
import java.util.regex.Pattern;
 
public class ThreeWays {
    public static void main(String[] args) {
        Pattern pin = Pattern.compile("\\d{6}");
        System.out.println(pin.matcher("411001").matches());
        System.out.println(pin.matcher("4110012").matches());
        System.out.println(pin.matcher("PIN 411001").find());
        System.out.println(pin.matcher("PIN 411001").lookingAt());
    }
}
Output
true
false
true
false
MethodQuestionTypical use
matches()Does the whole text fit the pattern?Validating input: a PIN code, an email
find()Does the pattern appear anywhere?Searching and extracting
lookingAt()Does the text start with the pattern?Parsing a prefix

"4110012" has 7 digits, so it doesn't match as a whole, even though it contains six digits. That difference catches many beginners.

Why Compile Once

Compiling turns the pattern into an internal structure the engine can run, and that takes time. If a method validates thousands of emails, compiling the same pattern on every call wastes it. Keep frequently used patterns in a static final field:

Reuse
private static final Pattern PIN = Pattern.compile("\\d{6}");
 
static boolean isValidPin(String text) {
    return PIN.matcher(text).matches();
}

A Pattern is immutable and thread-safe, so one shared instance can serve the whole program. A Matcher is not; create a new one for each text.

Getting All Matches at Once

Since Java 9, results() returns every match as a stream, which can be turned into a list:

AllMatches.java▶ Try it
import java.util.regex.MatchResult;
import java.util.regex.Pattern;
 
public class AllMatches {
    public static void main(String[] args) {
        var numbers = Pattern.compile("\\d+")
            .matcher("Order 12 has 3 items for Rs. 450")
            .results()
            .map(MatchResult::group)
            .toList();
        System.out.println(numbers);
    }
}
Output
[12, 3, 450]

Flags and Errors

Flags change how a pattern behaves, such as ignoring case: Pattern.compile("java", Pattern.CASE_INSENSITIVE) finds "JAVA" too. A pattern with a mistake in it throws PatternSyntaxException when compiled; for "(abc" the description is Unclosed group.

Common Mistakes

Writing "\d" instead of "\\d". Java strings need the backslash escaped; "\d" is a compile error.

Using matches() to search inside text. It checks the whole text; use find().

Compiling the same pattern inside a loop. Compile once into a static final field.

Interview Corner

What are Pattern and Matcher in Java?

Pattern is an immutable, thread-safe compiled representation of a regular expression, created with Pattern.compile. Matcher is a stateful engine that applies a pattern to a specific input, created with pattern.matcher(text), and offers matches, find, lookingAt, group, start and end. Patterns are usually compiled once and reused; a new matcher is created for each input.

What is the difference between matches() and find()?

matches() succeeds only if the entire input matches the pattern. find() searches for the next subsequence that matches, anywhere in the input, and can be called repeatedly to find all matches.

Practice

  1. Easy: Find every 4-digit year in "Joined 2019, promoted 2023, moved 2026" and print each with its position.
  2. Harder: Write static List<String> hashtags(String post) that returns every hashtag (a # followed by letters or digits) in a social media post.

Quick check: Regex basics

4 questions
1What does \d{6} describe?
2How do you write \d in a Java string?
3Pattern.compile("\\d{6}").matcher("PIN 411001").matches() is:
4Which object is safe to share between threads?

Key Takeaways

Was this tutorial helpful?

Lesson 209 of 482