Long.parseLong("string")
throws an error if string is not parsable into long.
Is there a way to validate the string faster than using try-catch
?
Thanks
14 Answers
You can create rather complex regular expression but it isn't worth that. Using exceptions here is absolutely normal.
It's natural exceptional situation: you assume that there is an integer in the string but indeed there is something else. Exception should be thrown and handled properly.
If you look inside parseLong
code, you'll see that there are many different verifications and operations. If you want to do all that stuff before parsing it'll decrease the performance (if we are talking about parsing millions of numbers because otherwise it doesn't matter). So, the only thing you can do if you really need to improve performance by avoiding exceptions is: copy parseLong
implementation to your own function and return NaN instead of throwing exceptions in all correspondent cases.

- 39,912
- 17
- 102
- 155

- 64,384
- 92
- 238
- 332
-
2@Roman: and there lots of usually pointless and needless things, like working in base others than 10 and parsing digits that are non-ASCII. Which is why you can rewrite a parseBase10AsciiDigitsLong(...) that is faster than the default Long.parseLong. But I'm sure every single brainfart from the Java gods cannot be discussed... – SyntaxT3rr0r Apr 01 '10 at 22:50
From commons-lang StringUtils:
public static boolean isNumeric(String str) {
if (str == null) {
return false;
}
int sz = str.length();
for (int i = 0; i < sz; i++) {
if (Character.isDigit(str.charAt(i)) == false) {
return false;
}
}
return true;
}

- 42,748
- 17
- 132
- 221
-
9
-
12Oh guys, how about everything? The method gives a basic clue, or is it not enough? – lexicore Apr 01 '10 at 21:06
-
16Guys/Gals-if any?!!!! Come on . How come calling another method with `if` condition in a `for` loop ever be "faster" than `try{ Long.parseLong( string ) }catch(Exception e){}` - I think the question as well as this answer deserves a down voting. Do not *over-engineer* – ring bearer Apr 01 '10 at 21:08
-
1
-
@lexicore - if your question is directed at me, I would say you will end up re-implementing `Long.parseLong()` by refining/robust-ifying the snippet you provided - take no offense. That's all. – ring bearer Apr 01 '10 at 21:19
-
@lexicore: No, it's not enough. Because it doesn't correctly handle all possible strings - like `Long.parseLong()` does. The implication of your short function, and suggestions for regexes and the like, is that it can be simply done and would save time. It's not trivially simple, and you would be hard pressed to do better than `Long.parseLong()`. Implying otherwise does a disservice to the OP and other readers. – Carl Manaster Apr 01 '10 at 21:24
-
4@ring bearer: Long.parseLong() also supports non-decimal radixes. Therefor what I'd end up with would be a bit simpler and faster. However I agree that catching an exception is fully ok here. Was just trying to answer the original question instead of altering it - just for fun. ps. No offense, surely. I'm sorry if my words could seem like assuming that. – lexicore Apr 01 '10 at 21:26
-
2@lexicore: don't worry, you're not the only one... It's just that on SO there are really a lot of weird "programmers" all engaging in some kind of "groupthink": freethought is frowned upon here. Don't dare about suggesting something else than a default library, because these programmers uses these default libraries all the time. They couldn't be *writing* them, so they defend them. You can see that pattern on soooo many question on SO it's not even funny. I'll call these "programmers" the *"default-API-kneejerkers"* from now on ;) – SyntaxT3rr0r Apr 01 '10 at 22:46
-
@WizardOfOdds - Thanks for the knee jerk comment; any average joe can see the source of `parseLong()` using netbeans these days; Me being one has seen it. And what makes you guys think checking non-decimal radix is an issue? – ring bearer Apr 01 '10 at 23:53
-
It's old as Java let's you use `10_000_000L` as a legal Long value – Chris Suszyński Jul 03 '19 at 10:06
-
Be careful with `StringUtils.isNumeric`. `org.apache.commons.lang3.StringUtils.isNumeric("") = false` but `org.apache.commons.lang.StringUtils.isNumeric("") = true` – miloxe Mar 02 '22 at 14:24
You could do something like
if(s.matches("\\d*")){
}
Using regular expression - to check if String s is full of digits. But what do you stand to gain? another if condition?

- 20,383
- 7
- 59
- 72
-
1what about negative numbers? or very big numbers which cannot fit in long – Roman Apr 01 '10 at 21:04
-
1@Roman - I was only trying to give an idea here. Length check and refining of regex can be done. Ex: `s.matches("[+|-]\\d*")` will take care of + or - signs. The whole point of my answer was- why not still use `try/catch` instead of redundant *under-performing* checks? – ring bearer Apr 01 '10 at 21:13
-
1This doesn't check length of long as well as MAX_LONG value, sign and so on. – Alexey Sviridov Nov 05 '15 at 08:08
-
Pls see my response to similar comment above. I was just hinting towards using regex. Was not really giving a solution as handling exception is the right thing that OP should do. – ring bearer Nov 05 '15 at 08:31
org.apache.commons.lang3.math.NumberUtils.isParsable(yourString) will determine if the string can be parsed by one of: Integer.parseInt(String), Long.parseLong(String), Float.parseFloat(String) or Double.parseDouble(String)
Since you are interested in Longs you could have a condition that checks for isParsable and doesn't contain a decimal
if (NumberUtils.isParsable(yourString) && !StringUtils.contains(yourString,".")){ ...

- 843
- 9
- 22
-
that said, I don't expect its faster than just a try / catch on parseLong – Andrew Norman May 10 '17 at 00:53
-
Seems to be faster - https://www.baeldung.com/java-check-string-number – Ravi A. Jul 08 '23 at 05:44
This is a valid question because there are times when you need to infer what type of data is being represented in a string. For example, you may need to import a large CSV into a database and represent the data types accurately. In such cases, calling Long.parseLong and catching an exception can be too slow.
The following code only handles ASCII decimal:
public class LongParser {
// Since tryParseLong represents the value as negative during processing, we
// counter-intuitively want to keep the sign if the result is negative and
// negate it if it is positive.
private static final int MULTIPLIER_FOR_NEGATIVE_RESULT = 1;
private static final int MULTIPLIER_FOR_POSITIVE_RESULT = -1;
private static final int FIRST_CHARACTER_POSITION = 0;
private static final int SECOND_CHARACTER_POSITION = 1;
private static final char NEGATIVE_SIGN_CHARACTER = '-';
private static final char POSITIVE_SIGN_CHARACTER = '+';
private static final int DIGIT_MAX_VALUE = 9;
private static final int DIGIT_MIN_VALUE = 0;
private static final char ZERO_CHARACTER = '0';
private static final int RADIX = 10;
/**
* Parses a string representation of a long significantly faster than
* <code>Long.ParseLong</code>, and avoids the noteworthy overhead of
* throwing an exception on failure. Based on the parseInt code from
* http://nadeausoftware.com/articles/2009/08/java_tip_how_parse_integers_quickly
*
* @param stringToParse
* The string to try to parse as a <code>long</code>.
*
* @return the boxed <code>long</code> value if the string was a valid
* representation of a long; otherwise <code>null</code>.
*/
public static Long tryParseLong(final String stringToParse) {
if (stringToParse == null || stringToParse.isEmpty()) {
return null;
}
final int inputStringLength = stringToParse.length();
long value = 0;
/*
* The absolute value of Long.MIN_VALUE is greater than the absolute
* value of Long.MAX_VALUE, so during processing we'll use a negative
* value, then we'll multiply it by signMultiplier before returning it.
* This allows us to avoid a conditional add/subtract inside the loop.
*/
int signMultiplier = MULTIPLIER_FOR_POSITIVE_RESULT;
// Get the first character.
char firstCharacter = stringToParse.charAt(FIRST_CHARACTER_POSITION);
if (firstCharacter == NEGATIVE_SIGN_CHARACTER) {
// The first character is a negative sign.
if (inputStringLength == 1) {
// There are no digits.
// The string is not a valid representation of a long value.
return null;
}
signMultiplier = MULTIPLIER_FOR_NEGATIVE_RESULT;
} else if (firstCharacter == POSITIVE_SIGN_CHARACTER) {
// The first character is a positive sign.
if (inputStringLength == 1) {
// There are no digits.
// The string is not a valid representation of a long value.
return null;
}
} else {
// Store the (negative) digit (although we aren't sure yet if it's
// actually a digit).
value = -(firstCharacter - ZERO_CHARACTER);
if (value > DIGIT_MIN_VALUE || value < -DIGIT_MAX_VALUE) {
// The first character is not a digit (or a negative sign).
// The string is not a valid representation of a long value.
return null;
}
}
// Establish the "maximum" value (actually minimum since we're working
// with negatives).
final long rangeLimit = (signMultiplier == MULTIPLIER_FOR_POSITIVE_RESULT)
? -Long.MAX_VALUE
: Long.MIN_VALUE;
// Capture the maximum value that we can multiply by the radix without
// overflowing.
final long maxLongNegatedPriorToMultiplyingByRadix = rangeLimit / RADIX;
for (int currentCharacterPosition = SECOND_CHARACTER_POSITION;
currentCharacterPosition < inputStringLength;
currentCharacterPosition++) {
// Get the current digit (although we aren't sure yet if it's
// actually a digit).
long digit = stringToParse.charAt(currentCharacterPosition)
- ZERO_CHARACTER;
if (digit < DIGIT_MIN_VALUE || digit > DIGIT_MAX_VALUE) {
// The current character is not a digit.
// The string is not a valid representation of a long value.
return null;
}
if (value < maxLongNegatedPriorToMultiplyingByRadix) {
// The value will be out of range if we multiply by the radix.
// The string is not a valid representation of a long value.
return null;
}
// Multiply by the radix to slide all the previously parsed digits.
value *= RADIX;
if (value < (rangeLimit + digit)) {
// The value would be out of range if we "added" the current
// digit.
return null;
}
// "Add" the digit to the value.
value -= digit;
}
// Return the value (adjusting the sign if needed).
return value * signMultiplier;
}
}

- 145
- 1
- 4
You can use java.util.Scanner
Scanner sc = new Scanner(s);
if (sc.hasNextLong()) {
long num = sc.nextLong();
}
This does range checking etc, too. Of course it will say that "99 bottles of beer"
hasNextLong()
, so if you want to make sure that it only has a long
you'd have to do extra checks.

- 376,812
- 128
- 561
- 623
-
1I remember reading somewhere that using Scanner for this purpose is a bad practice. – Anna Dec 05 '17 at 10:57
This case is common for forms and programs where you have the input field and are not sure if the string is a valid number. So using try/catch with your java function is the best thing to do if you understand how try/catch works compared to trying to write the function yourself. In order to setup the try catch block in .NET virtual machine, there is zero instructions of overhead, and it is probably the same in Java. If there are instructions used at the try keyword then these will be minimal, and the bulk of the instructions will be used at the catch part and that only happens in the rare case when the number is not valid.
So while it "seems" like you can write a faster function yourself, you would have to optimize it better than the Java compiler in order to beat the try/catch mechanism you already use, and the benefit of a more optimized function is going to be very minimal since number parsing is quite generic.
If you run timing tests with your compiler and the java catch mechanism you already described, you will probably not notice any above marginal slowdown, and by marginal I mean it should be almost nothing.
Get the java language specification to understand the exceptions more and you will see that using such a technique in this case is perfectly acceptable since it wraps a fairly large and complex function. Adding on those few extra instructions in the CPU for the try part is not going to be such a big deal.

- 31
- 1
I think that's the only way of checking if a String is a valid long value. but you can implement yourself a method to do that, having in mind the biggest long value.

- 15,908
- 12
- 46
- 47
There are much faster ways to parse a long than Long.parseLong. If you want to see an example of a method that is not optimized then you should look at parseLong :)
Do you really need to take into account "digits" that are non-ASCII?
Do you really need to make several methods calls passing around a radix even tough you're probably parsing base 10?
:)
Using a regexp is not the way to go: it's harder to determine if you're number is too big for a long: how do you use a regexp to determine that 9223372036854775807 can be parsed to a long but that 9223372036854775907 cannot?
That said, the answer to a really fast long parsing method is a state machine and that no matter if you want to test if it's parseable or to parse it. Simply, it's not a generic state machine accepting complex regexp but a hardcoded one.
I can both write you a method that parses a long and another one that determines if a long can be parsed that totally outperforms Long.parseLong().
Now what do you want? A state testing method? In that case a state testing method may not be desirable if you want to avoid computing twice the long.
Simply wrap your call in a try/catch.
And if you really want something faster than the default Long.parseLong, write one that is tailored to your problem: base 10 if you're base 10, not checking digits outside ASCII (because you're probably not interested in Japanese's itchi-ni-yon-go etc.).

- 27,745
- 21
- 87
- 120
-
In addition to that I may add that in your problem space, it is very unlikely that by some magic the maximum and minimum long you'd need to parse would exactly match -2**63+1 and 2**63 (unless your problem space happens to be the computing space). Which means a custom made state machine can be even better performing than a "normal" parselong, allowing to parse any long from -2**63+1 to 2**63 (and, yup, I've (re)written "parse long" much faster than Long.parseLong and they're in production code on a *lot* of systems ;) – SyntaxT3rr0r Apr 01 '10 at 22:39
Hope this helps with the positive values. I used this method once for validating database primary keys.
private static final int MAX_LONG_STR_LEN = Long.toString(Long.MAX_VALUE).length();
public static boolean validId(final CharSequence id)
{
//avoid null
if (id == null)
{
return false;
}
int len = id.length();
//avoid empty or oversize
if (len < 1 || len > MAX_LONG_STR_LEN)
{
return false;
}
long result = 0;
// ASCII '0' at position 48
int digit = id.charAt(0) - 48;
//first char cannot be '0' in my "id" case
if (digit < 1 || digit > 9)
{
return false;
}
else
{
result += digit;
}
//start from 1, we already did the 0.
for (int i = 1; i < len; i++)
{
// ASCII '0' at position 48
digit = id.charAt(i) - 48;
//only numbers
if (digit < 0 || digit > 9)
{
return false;
}
result *= 10;
result += digit;
//if we hit 0x7fffffffffffffff
// we are at 0x8000000000000000 + digit - 1
// so negative
if (result < 0)
{
//overflow
return false;
}
}
return true;
}

- 2,018
- 25
- 32
Try to use this regular expression:
^(-9223372036854775808|0)$|^((-?)((?!0)\d{1,18}|[1-8]\d{18}|9[0-1]\d{17}|92[0-1]\d{16}|922[0-2]\d{15}|9223[0-2]\d{14}|92233[0-6]\d{13}|922337[0-1]\d{12}|92233720[0-2]\d{10}|922337203[0-5]\d{9}|9223372036[0-7]\d{8}|92233720368[0-4]\d{7}|922337203685[0-3]\d{6}|9223372036854[0-6]\d{5}|92233720368547[0-6]\d{4}|922337203685477[0-4]\d{3}|9223372036854775[0-7]\d{2}|922337203685477580[0-7]))$
It checks all possible numbers for Long.
But as you know in Java Long can contain additional symbols like +
, L
, _
and etc. And this regexp doesn't validate these values. But if this regexp is not enough for you, you can add additional restrictions for it.

- 61
- 3
Guava Longs.tryParse("string") returns null instead of throwing an exception if parsing fails. But this method is marked as Beta right now.

- 580
- 8
- 10
You could try using a regular expression to check the form of the string before trying to parse it?

- 925
- 9
- 16
A simple implementation to validate an integer that fits in a long would be:
public static boolean isValidLong(String str) {
if( str==null ) return false;
int len = str.length();
if (str.charAt(0) == '+') {
return str.matches("\\+\\d+") && (len < 20 || len == 20 && str.compareTo("+9223372036854775807") <= 0);
} else if (str.charAt(0) == '-') {
return str.matches("-\\d+") && (len < 20 || len == 20 && str.compareTo("-9223372036854775808") <= 0);
} else {
return str.matches("\\d+") && (len < 19 || len == 19 && str.compareTo("9223372036854775807") <= 0);
}
}
It doesn't handle octal, 0x prefix or so but that is seldom a requirement.
For speed, the ".match" expressions are easy to code in a loop.

- 1,300
- 1
- 12
- 28