Regular Expressions in Java
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
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());
}
}
}411001 at 13-19
500081 at 28-34How it works
\d{6}means "a digit, exactly 6 times". In a Java string, the backslash itself must be escaped, so you write"\\d{6}".Pattern.compileturns the pattern text into aPatternobject, ready to use.pattern.matcher(text)creates aMatcherfor one piece of text.- Each
find()searches forward from where the last match ended. It returnstrueand remembers the match, orfalsewhen there are no more. group()is the matched text;start()andend()are its positions (end excluded, likesubstring).
find, matches and lookingAt
The three ways to apply a pattern answer different questions:
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());
}
}true
false
true
false| Method | Question | Typical 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:
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:
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);
}
}[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
- Easy: Find every 4-digit year in
"Joined 2019, promoted 2023, moved 2026"and print each with its position. - Harder: Write
static List<String> hashtags(String post)that returns every hashtag (a#followed by letters or digits) in a social media post.
Key Takeaways
Was this tutorial helpful?