Explain Codes LogoExplain Codes Logo

Determine if a String is an Integer in Java

java
input-validation
regex-patterns
best-practices
Anton ShumikhinbyAnton Shumikhin·Dec 24, 2024
TLDR

Let's quickly determine if a string is an integer in Java using a try-catch block and Integer.parseInt(). True if no exception; false if NumberFormatException is thrown.

boolean isInteger(String str) { try { Integer.parseInt(str); // I like my booleans like I like my Java: strongly-typed return true; } catch (NumberFormatException e) { // An exception a day keeps the integer away return false; } }

Usage example:

boolean isInt = isInteger("123"); // true, the magic number always works

The efficiency conundrum

While the exception handling method is your trusty horse, it's not a racehorse when it comes to efficiency due to the cost of throwing exceptions.

So, how do we give wings to our code?

Look to Regex:

boolean isIntegerRegex(String str) { // Is it a bird? Is it a plane? No, it's Integerman! return str.matches("-?\\d+"); }

Or to Apache Commons Lang (if available), that is if you are OK with it ignoring negative values:

boolean isInt = StringUtils.isNumeric("123"); // true, but I swear it was bigger when I measured it

Remember, one size doesn't fit all: choose an approach based on your project's needs and dependencies.

When size does matter

Admittedly, Java is not good with very large numbers. When numbers surpass Integer.MAX_VALUE or fall below Integer.MIN_VALUE, Integer.parseInt() throws an exception, and our regex approach just gives it a pass 🤷‍♀️.

Introducing BigInteger for such cases:

boolean isIntegerSafe(String str) { try { // Like Integer.parseInt(), but on steroids new BigInteger(str); return true; } catch (NumberFormatException e) { return false; } }

Remember:

  • BigInteger can realistically crunch any numeric string length but might be overkill
  • For bounding integer size, a preemptive length check could be worthwhile
  • Google's Guava library provides Ints.tryParse(), savvier than Integer.parseInt() and less verbose than exceptions

Precision with Regular Expressions

Fancy more precision? Regex is your loyal companion, especially when excluding leading zeros or regulating signed numbers.

To match integers (including negatives) without leading zeros:

boolean isPreciseIntegerRegex(String str) { // Better accuracy than my wristwatch return str.matches("-?(0|[1-9]\\d*)"); }

Note: \\d+ nebulously matches numbers with leading zeros too.

Edge Cases and Best Practices

Edge Case handling: Unicode Digits

Our methods have a blind spot: Unicode numeric characters. For wide coverage, iterate over characters with Character.isDigit().

boolean isIntegerUnicode(String str) { for (char ch : str.toCharArray()) { if (!Character.isDigit(ch)) { // Unicode playing hide and seek here return false; } } return str.length() > 0; // Empty strings are as good as saying nothing }

Best Practices: Input Validation

Always sanitize and validate your inputs be it user-input or external data. Protector of realms - Input Validation defends your code from questionable data, and keeps security risks such as injection attacks at bay.

Pitfalls: Large String Handling

When devising a method to verify if a string is an integer, one must brace themselves for overly large inputs which can lead to hidden gremlins or performance snags.

Scenario Management: Sorting Strings as Integers

When you're sorting string-lists as integers, validate their integrality first. Else, you may find "100" leading before "20". So, parse, then sort or wield a custom comparator:

Collections.sort(stringList, (a, b) -> { if (isInteger(a) && isInteger(b)) { // I'm at the wheel, manual comparator return Integer.compare(Integer.parseInt(a), Integer.parseInt(b)); } return a.compareTo(b); });