346

I'm trying to determine if a particular item in an Array of strings is an integer or not.

I am .split(" ")'ing an infix expression in String form, and then trying to split the resultant array into two arrays; one for integers, one for operators, whilst discarding parentheses, and other miscellaneous items. What would be the best way to accomplish this?

I thought I might be able to find a Integer.isInteger(String arg) method or something, but no such luck.

Ben
  • 3,989
  • 9
  • 48
  • 84
Nick Coelius
  • 4,668
  • 3
  • 24
  • 30
  • I do not understand with several java updates, such easy helper methods are not being made built in into the kit. – tony9099 Sep 30 '13 at 14:08
  • @tony9099 it's kind of an edgecase situation and, from what I've seen slash the fact that this question still gets views, fairly unique. The accepted workaround (that I accepted as an answer) is probably better than making it Java standard. – Nick Coelius Oct 02 '13 at 22:59
  • 2
    @Nick to further your argument that it's not necessary to be in Java, only about one in every 772 visitors decided to vote up my answer, despite there being three useful solutions (admittedly, each better than the previous one). I think that is a clear indicator this is an edge case where in most cases you're better off changing the way you solve the problem such that you don't need my solution instead of actually using it. – corsiKa Oct 04 '13 at 16:22

9 Answers9

362

The most naive way would be to iterate over the String and make sure all the elements are valid digits for the given radix. This is about as efficient as it could possibly get, since you must look at each element at least once. I suppose we could micro-optimize it based on the radix, but for all intents and purposes this is as good as you can expect to get.

public static boolean isInteger(String s) {
    return isInteger(s,10);
}

public static boolean isInteger(String s, int radix) {
    if(s.isEmpty()) return false;
    for(int i = 0; i < s.length(); i++) {
        if(i == 0 && s.charAt(i) == '-') {
            if(s.length() == 1) return false;
            else continue;
        }
        if(Character.digit(s.charAt(i),radix) < 0) return false;
    }
    return true;
}

Alternatively, you can rely on the Java library to have this. It's not exception based, and will catch just about every error condition you can think of. It will be a little more expensive (you have to create a Scanner object, which in a critically-tight loop you don't want to do. But it generally shouldn't be too much more expensive, so for day-to-day operations it should be pretty reliable.

public static boolean isInteger(String s, int radix) {
    Scanner sc = new Scanner(s.trim());
    if(!sc.hasNextInt(radix)) return false;
    // we know it starts with a valid int, now make sure
    // there's nothing left!
    sc.nextInt(radix);
    return !sc.hasNext();
}

If best practices don't matter to you, or you want to troll the guy who does your code reviews, try this on for size:

public static boolean isInteger(String s) {
    try { 
        Integer.parseInt(s); 
    } catch(NumberFormatException e) { 
        return false; 
    } catch(NullPointerException e) {
        return false;
    }
    // only got here if we didn't return false
    return true;
}
Pétur Ingi Egilsson
  • 4,368
  • 5
  • 44
  • 72
corsiKa
  • 81,495
  • 25
  • 153
  • 204
  • 3
    You'll note that this does not check for null. We're willing to let the null pointer exception get thrown. If you want to handle that, you can. I chose not to, but rather to delegate it up. – corsiKa Mar 26 '11 at 00:36
  • 1
    try/catch block for that? I think that is a bit excessive for this task as throwing an exception can be expensive and if a number of strings are not integers then you get expense. – demongolem Dec 16 '11 at 16:57
  • @demongolem I added non-exception based method. – corsiKa Dec 16 '11 at 17:38
  • 4
    The "non exception based method" will consider "-" to be an integer. – Zach Langley Sep 05 '12 at 15:45
  • @ZachLangley Good call. Added a fix for that. – corsiKa Jan 09 '13 at 18:08
  • In you loop condition, `s.length` should be `s.length()` – Harshal Waghmare May 29 '13 at 07:28
  • 1
    I used the exception based method and a coworker called me out for using an antipattern, was a learning experience for me. – eric Mar 03 '15 at 17:04
  • 6
    It certainly is an unorthodox way to do it. As general rule, you want to avoid using exceptions to dictate execution flow. Or as Joshua Bloch puts it in his "Effective Java item 57: Use exceptions only for exceptional conditions." His comment on using exceptions to iterate over an array is `// Horrible abuse of exceptions. Don't ever do this!` actually – corsiKa Mar 03 '15 at 17:53
  • 1
    @eric It's a few years old, but I took the time to clean up this post to elaborate what is good and what is bad about the various methods. – corsiKa Mar 03 '15 at 17:58
  • @corsiKa thanks! Your comments about trolling the code reviewer made my day. – eric Mar 03 '15 at 18:47
  • @eric - Java exception performance has improved significantly, but, I have personally witnessed a CSV parsing routine improve performance by about 10-times by first running a regex on the value before trying to parse it as an integer, instead of just an unregulated try/catch – rolfl Mar 03 '15 at 19:25
  • 4
    Could somebody explain to me why the 3rd method is bad practice? Because of basing the execution flow on exceptions? – Sebastian Breit May 24 '15 at 17:10
  • 66
    They're called "exceptions" for a reason. In a perfect world, you never get an exception. Say my boss asks me to work on an assignment. He'll expect me to say "yes, sir!" but I might reply with "I have a lot on my plate right now, I can't accept a new assignment without letting existing work fall through." He is prepared for both of those. He isn't prepared for me to punch him in the face. I lose my job and he calls security. Now imagine if he called security for me simply saying I have too much work - that's the third method: calling the cops for something that should just be expected. – corsiKa May 24 '15 at 22:40
  • Exception handles can't return a value. Outright bogus. – Smart Coder Sep 04 '16 at 23:01
  • @SmartCoder Well, I generally would recommend against returning from a catch block, but that doesn't mean it's impossible. Granted that is in there more as a joke than anything else, but it's valid code nevertheless. – corsiKa Sep 06 '16 at 00:10
  • @corsiKa Let's say I am reading input from a file. I am expecting a specific syntax, but I get invalid input. Would that be a valid situation to use your 3rd method? I am writing an assembler, and I was planning on creating a super class with sub exception classes for different types of illegal inputs - would that be a good use of java exception? – Quazi Irfan Oct 08 '16 at 04:54
  • 2
    @iamcreasy Generally I'd still say no. Your method is either one of two things: either it tests validity or it does actual work. If it tests validity it should find a way to do it without an exception because a validity test should expect invalid input sometimes. If it's an actual work method, it should just bubble up the exception unless you're wrapping the exception in a framework specific exception. – corsiKa Oct 08 '16 at 15:42
  • @corsiKa Yes, its an work method, and checking for different kinds of errors is create a large chunks of unwieldy if-else statements; and its showing it's weight when I have to add one more error condition. So in what type of similar situations - exception would be an acceptable choice? Also I don't understand what you mean by "it should just bubble up the exception unless you're wrapping the exception in a framework specific exception." Could you please clarify a little more? – Quazi Irfan Oct 08 '16 at 18:46
  • 1
    @corsiKa Your "punch your boss in the face" comment is probably the best comment I've read on SO, while also being one of the best explained examples. +1 to you, sir. – Zig Nov 29 '16 at 16:43
  • 8
    Using the non exception method the string "9999999999999999999999" is a valid integer – fgonzalez Dec 03 '16 at 09:49
  • @fgonzalez and, depending on your definition of integer, that is a valid integer. It just happens to not fit in a `java.lang.Integer`. Doesn't mean it isn't an integer. – corsiKa Dec 03 '16 at 16:47
  • In reality, the perfect validation is done by actually trying it. Can you drink 2 six-packs of beer in one night? Unless you tried it, you can't say for sure. You might make the SWAG based on the past drinking experience which is still an expectation you can't prove. In this case, whether a String is an integer can be proven before calling Integer.parseInt(..). But, the fact that Integer.parseInt(..) throws an Exception means that it does validation itself and this will cause some validation to run twice on a String. – Sgene9 Jun 23 '18 at 02:44
  • 2
    Also, what is "exceptional"? How much certainty should be betrayed for the situation to be "exceptional"? 99%? 90%? 75%? From your punching-the-boss-in-the-face example, which is hilarious, when would you say that it is appropriate the call the cops? When you say, "I have a lot on my plate..." sentence with louder voice? How much louder? The term "exceptional" or "expected" is so subjective, that it can't be used to describe when something is used. I think we should rather think it simpler. A String is an integer, only if it can be an integer. How do we know if it can be an integer? Try it. – Sgene9 Jun 23 '18 at 02:55
  • @Sgene9 Try not to think of "exceptional" as an English word. Rather it very specifically means "input or state for which this program was not designed to handle." And so, by definition, you don't want exceptions. Throwing of exceptions is an expensive operation and should not be part of your intended flow. If you're using exceptions for control flow, you're probably doing it wrong. – corsiKa Jun 23 '18 at 16:37
  • Hi, Any reason behind using this condition "s.charAt(0) == '-'". I am unable to relate "-" character at 0 index ? – Aashu Jul 19 '21 at 14:26
  • 1
    @Aashu because `"-1234"` should resolve to an integer – corsiKa Jul 20 '21 at 02:24
  • I've got same argument on the "9999999999999999999999" being as a valid integer using the non exception method. Indeed, it is a valid integer. But because this is a question very specific to java, I guess the constraint of java should also apply here. Hence, this number should not be a valid integer. – Lichader Oct 25 '22 at 06:56
  • @Lichader I mean, there is literally a `BigInteger` class for integers too big to fit in an `Integer`, which this certainly would work for. – corsiKa Oct 31 '22 at 18:18
  • Honestly, given how many benefits parseInt is offering, implementing your own isInteger method for most common use cases to avoid exceptions just because someone said "exceptions are bad" (or in similar mood) is twice as horrible as using exceptions to control the flow. – Turkhan Badalov Apr 25 '23 at 10:58
304

It's better to use regular expression like this:

str.matches("-?\\d+");

-?     --> negative sign, could have none or one
\\d+   --> one or more digits

It is not good to use NumberFormatException here if you can use if-statement instead.

If you don't want leading zero's, you can just use the regular expression as follow:

str.matches("-?(0|[1-9]\\d*)");
Apostolos
  • 10,033
  • 5
  • 24
  • 39
shuangwhywhy
  • 5,475
  • 2
  • 18
  • 28
  • 17
    Also... If anyone wants to deal with the signal '+', I made that version (Regarding to yours) : `str.matches("^[+-]?\\d+$")` – Damiii Apr 09 '15 at 10:46
  • 19
    Curious as to why this isn't the chosen answer... – Brent Hronik Jun 02 '15 at 00:04
  • 7
    @BrentHronik It's a nice clean one-liner, but according to one of the answers at http://stackoverflow.com/questions/237159/whats-the-best-way-to-check-to-see-if-a-string-represents-an-integer-in-java, it's 10x slower than the methods suggested by corsiKa. – lreeder Jul 05 '15 at 15:04
  • During initialisation, checking the value of configuration input strings, performance isn't an issue +1 – Adam May 15 '17 at 10:43
  • The leading ^ and trailing $ in the regular expression are redundant since String.matches() always matches the whole string. – Shon Vella Jun 01 '17 at 22:17
  • 2
    I downvoted. Reason: The question is to check whether the given string is integer or not. The integer has a limit for number of digits ranging -2147483648 to 2147483647. If you provide more char in your string than the limit, regex will pass it. – smilyface Jun 10 '22 at 08:34
  • 1
    @smilyface, exactly. I would understand why people blame using exceptions if Java had `isInt` method and someone still used `parseInt` for checking int via exceptions. Unfortunately, there is no other method for that, and given how many validations parseInt is performing for us, implementing custom methods just to "avoid exceptions" or "fitting best practices" is nothing but over-engineering in the best case. As we know sometimes doing X instead of Y is better although Y is preffered in general. – Turkhan Badalov Apr 25 '23 at 11:09
162

Or you can enlist a little help from our good friends at Apache Commons : StringUtils.isNumeric(String str)

Will Madison
  • 3,065
  • 2
  • 22
  • 19
  • 3
    The only question I have about this method is "" returning true. Our intuition tells us that the empty string is not a number (Integer for the OP question) you can perform mathematical operations on, but I guess you can say you cannot prove that the empty string is non-numeric because we haven't told you yet what the String will be. – demongolem Dec 16 '11 at 17:02
  • 18
    I wish this was a good answer for me, but not only does "" return true but also "-1" will return false. That means that it will neither return true for all valid integers nor will the fact that it returns true guarantee that passing it to Integer.parseInt will not throw an exception. – jhericks Apr 04 '13 at 02:41
  • 5
    @jhericks Thanks for pointing that out. When I first answered this a couple of years ago it was referencing an older version of Commons StringUtils. They have since updated the api such that empty string is now considered non-numeric. Unfortunately the negative case would have to be handled separately which is a drawback but the work around is trivial. Simply a check for numberCandidate.startsWith("-") and a substring call with a negation after the parseInt call assuming the value was numeric of course. – Will Madison Apr 05 '13 at 07:14
  • 4
    Not only is `StringUtils.isNumeric(String)` not fulfilling the original request to check if a string "is an integer or not", but also suggesting a beast like the apache commons in order to avoid writing a one-liner is not rational imho. – Björn Zurmaar Jul 08 '17 at 22:27
  • Just avoid Apache "commons" at all costs. While sometimes a good idea at first sight, it's just a bunch of antipatterns that will bring you dependency hell, for debatable results. – ymajoros Oct 04 '17 at 05:20
  • There's also `NumberUtils.isNumber(str)`. Note however that both do not check for Integer as a type (max and min value restrictions) but for numbers in general. – Terran Dec 01 '17 at 13:32
79

You want to use the Integer.parseInt(String) method.

try{
  int num = Integer.parseInt(str);
  // is an integer!
} catch (NumberFormatException e) {
  // not an integer!
}
Mike Lewis
  • 63,433
  • 20
  • 141
  • 111
  • 4
    Why is this not higher rated? It seems the simplest to me, or are there some downsides I am missing? – bobismijnnaam Apr 14 '16 at 08:14
  • 15
    @bobismijnnaam The problem with this is, that it generates a relative expensive exception and you have some nasty nesting, which may affect readability. – Zhedar Apr 20 '16 at 19:29
  • 8
    Exceptions are indicating that something went wrong, and this kind of usage surely is an abuse of this design principle. Only use Integer.parserInt() **after** you ensured, that the String really contains an integer value. If doing so and Integer.parseInt still throws an exception, then you know that you have a problem in your code which you should fix (or, for the sake of completeness, that Integer.parseInt itself is buggy, but this option is quite unlikely) – Rolch2015 Sep 01 '16 at 20:18
  • not worked and converted aaaa into some value – Khwaja Sanjari Mar 15 '19 at 04:55
77

Or simply

mystring.matches("\\d+")

though it would return true for numbers larger than an int

strah
  • 6,702
  • 4
  • 33
  • 45
claus437
  • 819
  • 6
  • 2
  • 8
    doesn't work. matches any string that contains 1 or more digits in a row. for example, `blabla. 0 bla bla bla` matches. – njzk2 Sep 13 '13 at 14:38
  • 15
    @njzk2 use `"^-?\\d+$"` as your regex – Sujay Sep 18 '13 at 13:42
  • 2
    what about values x with x > Integer.MaxValue, same for min? – Martin Meeser Oct 19 '16 at 09:13
  • njzk2 - it does work because String.matches() only returns true if the whole string matches the pattern, though you have to follow the documentation trail from String.matches() to Pattern.matches() to [Matcher.matches()](https://docs.oracle.com/javase/8/docs/api/java/util/regex/Matcher.html#matches) to discover that fact. – Shon Vella Jun 01 '17 at 22:25
  • Works fine for numbers less than Integer.MaxValue. This solution shows bad performance though. Have a look at the benchmark here: https://www.baeldung.com/java-check-string-number – javadev Dec 19 '19 at 17:56
  • I downvoted. Reason: The question is to check whether the given string is integer or not. The integer has a limit for number of digits ranging -2147483648 to 2147483647. If you provide more char in your string than the limit, regex will pass it. – smilyface Jun 10 '22 at 08:35
16

As an alternative approach to trying to parse the string and catching NumberFormatException, you could use a regex; e.g.

if (Pattern.compile("-?[0-9]+").matches(str)) {
    // its an integer
}

This is likely to be faster, especially if you precompile and reuse the regex.

However, the problem with this approach is that Integer.parseInt(str) will also fail if str represents a number that is outside range of legal int values. While it is possible to craft a regex that only matches integers in the range Integer.MIN_INT to Integer.MAX_INT, it is not a pretty sight. (And I am not going to try it ...)

On the other hand ... it may be acceptable to treat "not an integer" and "integer too large" separately for validation purposes.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
10

You can use Integer.parseInt(str) and catch the NumberFormatException if the string is not a valid integer, in the following fashion (as pointed out by all answers):

static boolean isInt(String s)
{
 try
  { int i = Integer.parseInt(s); return true; }

 catch(NumberFormatException er)
  { return false; }
}

However, note here that if the evaluated integer overflows, the same exception will be thrown. Your purpose was to find out whether or not, it was a valid integer. So its safer to make your own method to check for validity:

static boolean isInt(String s)  // assuming integer is in decimal number system
{
 for(int a=0;a<s.length();a++)
 {
    if(a==0 && s.charAt(a) == '-') continue;
    if( !Character.isDigit(s.charAt(a)) ) return false;
 }
 return true;
}
Rushil Paul
  • 2,010
  • 4
  • 26
  • 39
2

You can use Integer.parseInt() or Integer.valueOf() to get the integer from the string, and catch the exception if it is not a parsable int. You want to be sure to catch the NumberFormatException it can throw.

It may be helpful to note that valueOf() will return an Integer object, not the primitive int.

Chad La Guardia
  • 5,088
  • 4
  • 24
  • 35
  • edited for clarity. No need to be cheeky. – Chad La Guardia Mar 26 '11 at 01:41
  • @krmby the objective is not to actually retrieve the value, only to determine if it fits the format. In that regard, Chad is correct in that both of the methods will work just fine. – corsiKa Mar 28 '11 at 18:35
  • @glowcoder you are talking about edited version of the answer which i am not. I now both methods do the job fine but this does not change the fact that return type of `Integer.parseInt()` is `int`. – Kerem Baydoğan Mar 29 '11 at 11:21
  • @krmby ah an interesting point. I was focusing on the first paragraph (which as I review, remains unchanged.) – corsiKa Mar 29 '11 at 16:28
  • @glowcoder Author of this answer said: **It may be helpful to note that those methods will return an Integer object, not the primitive int**. I'm **ONLY** saying that `parseInt()` returns `int`. I said **NOTHING** about first paragraph. Chad La Guardia **CORRECTED** his answer according to my comment and everything is fine. So i'm not getting your point actually. – Kerem Baydoğan Mar 29 '11 at 17:23
  • @krmby yes I noticed that. What I'm saying was I wasn't aware there was an error only in the second paragraph, as I had largely ignored it. My actual assumption was that there was an error originally in the first paragraph and that the second paragraph was only added to appease your first comment. You actually said nothing about either paragraph, only that one returns an Integer instead of an int. I read, in the first sentence, "to get the integer from the string", which made me think that's what your reference was to. – corsiKa Mar 29 '11 at 17:57
0
public boolean isInt(String str){
    return (str.lastIndexOf("-") == 0 && !str.equals("-0")) ? str.substring(1).matches(
            "\\d+") : str.matches("\\d+");
}
Titus
  • 22,031
  • 1
  • 23
  • 33