Matcher.matches requires the entire input to satisfy a pattern, while find searches for the next matching subsequence.
Java Matcher.matches and find: whole-input validation versus extraction
Choose validation or search
An invoice identifier validator must reject a prefixed note, even if a valid-looking identifier appears inside it. A scanner looking for identifiers in log text has the opposite contract. Use matches for the former and find for the latter. Do not paper over this distinction with a leading and trailing wildcard.
A Matcher carries position and last-match state. Build a fresh matcher when changing the task, or call reset deliberately. Find cursor state shows what repeated calls consume.
Bound format and input
The pattern checks a compact ASCII identifier: two uppercase letters, a hyphen and four digits. Real invoice rules may include checksums and length ceilings that a simple regex does not supply. Treat this as a shape check, not proof that an invoice exists.
Working program
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class InvoiceIdBoundary {
public static void main(String[] args) {
Pattern invoiceShape = Pattern.compile("[A-Z]{2}-[0-9]{4}");
Matcher note = invoiceShape.matcher("paid AB-2741 today");
System.out.println("valid=" + note.matches());
System.out.println("found=" + note.find());
System.out.println("value=" + note.group());
}
}Output
valid=false
found=true
value=AB-2741Cost and ownership
For this fixed-width pattern, scanning is linear in input length and uses a small matcher state. Other regular expressions can backtrack heavily; validate length before matching and test the actual pattern against hostile inputs.
Common Mistakes
- Do not use find for a full-field validation rule.
- Do not call group before a successful match.
- Do not reuse a Matcher without accounting for its current scan position.
Read next
regex find cursor, Java Pattern.quote: match a supplied token literally, Java strings and content equality, regex group state.
