Introduction
Checking whether a string contains only digits is one of the most common validation tasks in Java. It is widely used when validating user input such as phone numbers, PINs, ZIP codes, invoice numbers, product IDs, and numeric form fields.
For example:
"12345"→ Valid"007"→ Valid"123abc"→ Invalid"123.45"→ Invalid"12 34"→ Invalid
Java offers several ways to perform this validation, ranging from simple character iteration to regular expressions and modern Stream API solutions.
This guide explores four different approaches, their advantages, limitations, performance characteristics, and real-world use cases.
Method 1: Using Character.isDigit() (Recommended)
The most efficient and commonly recommended approach is to examine each character using the Character.isDigit() method.
public class CheckOnlyDigits {
public static boolean containsOnlyDigits(String str) {
if (str == null || str.isEmpty()) {
return false;
}
for (char ch : str.toCharArray()) {
if (!Character.isDigit(ch)) {
return false;
}
}
return true;
}
public static void main(String[] args) {
System.out.println(containsOnlyDigits("12345"));
System.out.println(containsOnlyDigits("123 45"));
System.out.println(containsOnlyDigits("123.45"));
System.out.println(containsOnlyDigits("abc123"));
System.out.println(containsOnlyDigits("007"));
}
}
Output
true
false
false
false
true
How It Works
- Check for
nullor empty strings. - Iterate through every character.
- If any character is not a digit, immediately return
false. - If every character is a digit, return
true.
Advantages
- Fastest solution.
- Stops immediately when a non-digit is found.
- Supports Unicode digits.
- Easy to understand.
Disadvantages
- Slightly more code than a regex solution.
Time Complexity
O(n)
Space Complexity
O(1)
Method 2: Using Regular Expressions
Regular expressions provide a concise way to validate digit-only strings.
public class CheckOnlyDigitsRegex {
public static boolean containsOnlyDigits(String str) {
return str != null &&
str.matches("\\d+");
}
public static void main(String[] args) {
System.out.println(containsOnlyDigits("999"));
System.out.println(containsOnlyDigits("100ABC"));
System.out.println(containsOnlyDigits("007"));
}
}
Output
true
false
true
Understanding the Pattern
\d+
\d→ Any digit+→ One or more occurrences
Therefore:
12345 ✓
007 ✓
12A34 ✗
12.5 ✗
Advantages
- Very concise.
- Easy to reuse.
- Ideal for validation rules.
Disadvantages
- Regex introduces additional overhead.
- Slightly slower than direct character iteration.
Time Complexity
O(n)
Space Complexity
Depends on the regex engine implementation.
Method 3: Using Try-Catch with Long.parseLong()
Another approach is to attempt numeric parsing.
public class CheckOnlyDigitsParsing {
public static boolean containsOnlyDigits(String str) {
if (str == null || str.isEmpty()) {
return false;
}
try {
Long.parseLong(str);
return true;
} catch (NumberFormatException e) {
return false;
}
}
public static void main(String[] args) {
System.out.println(containsOnlyDigits("123"));
System.out.println(containsOnlyDigits("123.45"));
System.out.println(containsOnlyDigits("999999999999999999999999"));
}
}
Output
true
false
false
How It Works
If Long.parseLong() successfully parses the string, it must contain valid numeric characters.
If parsing fails, a NumberFormatException is thrown.
Advantages
- Very simple.
- Useful when numeric conversion is also required.
Disadvantages
- Fails for numbers larger than
Long.MAX_VALUE. - Uses exceptions for control flow.
- Slower than direct character checking.
Time Complexity
O(n)
Space Complexity
O(1)
Method 4: Using Stream API
Java Streams provide a modern functional approach.
public class CheckOnlyDigitsStream {
public static boolean containsOnlyDigits(String str) {
return str != null &&
!str.isEmpty() &&
str.chars()
.allMatch(Character::isDigit);
}
public static void main(String[] args) {
System.out.println(containsOnlyDigits("777"));
System.out.println(containsOnlyDigits("77.7"));
System.out.println(containsOnlyDigits("000"));
}
}
Output
true
false
true
How It Works
chars()converts the string into anIntStream.allMatch()verifies that every character satisfiesCharacter.isDigit().
Advantages
- Modern Java syntax.
- Easy to integrate into stream pipelines.
- Expressive and concise.
Disadvantages
- More overhead than loops.
- Less beginner-friendly.
Time Complexity
O(n)
Space Complexity
O(1)
Handling Common Variations
Allow Leading and Trailing Spaces
str = str.trim();
return !str.isEmpty() &&
str.chars()
.allMatch(Character::isDigit);
Allow Positive or Negative Numbers
public static boolean isValidInteger(String str) {
if (str == null || str.isEmpty()) {
return false;
}
if (str.startsWith("-") ||
str.startsWith("+")) {
str = str.substring(1);
}
return !str.isEmpty() &&
str.chars()
.allMatch(Character::isDigit);
}
Examples:
123 ✓
-456 ✓
+789 ✓
12A3 ✗
Allow Decimal Numbers
public static boolean isDecimal(String str) {
return str != null &&
str.matches("\\d+(\\.\\d+)?");
}
Examples:
123 ✓
45.67 ✓
12. ✗
.45 ✗
Allow Formatted Phone Numbers
String digitsOnly =
phone.replaceAll("[^0-9]", "");
return digitsOnly.length() == 10;
Example:
987-654-3210
↓
9876543210
Performance Comparison
| Method | Time Complexity | Space Complexity | Unicode Support | Recommended |
|---|---|---|---|---|
| Character.isDigit() | O(n) | O(1) | ✔ | ⭐⭐⭐⭐⭐ |
| Regular Expression | O(n) | Regex overhead | Depends | ⭐⭐⭐⭐ |
| Long.parseLong() | O(n) | O(1) | ✘ (numeric parsing only) | ⭐⭐⭐ |
| Stream API | O(n) | O(1) | ✔ | ⭐⭐⭐⭐ |
Practical Applications
Example 1: PIN Validation
public static boolean isValidPin(String pin) {
return pin != null &&
pin.length() == 4 &&
pin.chars()
.allMatch(Character::isDigit);
}
Example 2: Employee ID Validation
public static boolean isEmployeeId(String id) {
return id != null &&
id.matches("\\d{6}");
}
Example 3: ZIP Code Validation
public static boolean isZipCode(String zip) {
return zip != null &&
zip.matches("\\d{5}");
}
Example 4: Invoice Number Validation
public static boolean isInvoiceNumber(String invoice) {
return invoice != null &&
invoice.chars()
.allMatch(Character::isDigit);
}
Best Practices
Validate Null and Empty Strings
if (str == null || str.isEmpty()) {
return false;
}
Prefer Character.isDigit()
It is the fastest and most flexible solution.
Character.isDigit(ch)
Avoid Parsing for Validation
Parsing introduces unnecessary exceptions and numeric range limitations.
Trim User Input
str = str.trim();
Choose Regex for Fixed Formats
\\d{10}
is excellent for validating a fixed-length numeric value.
Frequently Asked Questions
Q1: Should I handle negative numbers?
Answer: Yes, if your application accepts them. Remove the leading + or - before checking the remaining characters.
Q2: Are leading zeros valid?
Answer: Yes. "007" contains only digits and should return true.
Q3: Does this work for decimal numbers?
Answer: No. "123.45" contains a decimal point, so it is not considered a digit-only string.
Q4: Should I trim whitespace?
Answer: Yes. User input often contains accidental leading or trailing spaces.
str = str.trim();
Q5: Which method is fastest?
Answer: The Character.isDigit() loop is generally the fastest because it performs direct character checks and exits immediately when it encounters a non-digit.
Q6: Does Character.isDigit() support Unicode?
Answer: Yes. It recognizes Unicode digit characters in addition to ASCII digits (0–9).
Q7: How should I handle null strings?
Answer: Always validate for null before processing.
if (str == null) {
return false;
}
Q8: Can I allow spaces between digits?
Answer: Not directly. Remove whitespace first if your application permits formatted input.
Q9: Why not use parseLong() for validation?
Answer: It fails for values outside the long range and relies on exceptions for normal program flow, making it less suitable for simple validation.
Q10: Which method should I use in production?
Answer: For most applications, Character.isDigit() provides the best combination of performance, readability, Unicode support, and flexibility.