137

Possible Duplicate:
Java: Good way to encapsulate Integer.parseInt()
how to convert a string to float and avoid using try/catch in java?

C# has Int.TryParse: Int32.TryParse Method (String, Int32%)

The great thing with this method is that it doesn't throw an exception for bad data.

In java, Integer.parseInt("abc") will throw an exception, and in cases where this may happen a lot performance will suffer.

Is there a way around this somehow for those cases where performance is an issue?

The only other way I can think of is to run the input against an regex, but I have to test to see what is faster.

Community
  • 1
  • 1
codecompleting
  • 9,251
  • 13
  • 61
  • 102
  • Throwing Exceptions doens't reduce perfomance, I think. Regex will be definitely slower. – Martijn Courteaux Dec 05 '11 at 21:19
  • 1
    Unfortunately, no. See this question for more details: http://stackoverflow.com/questions/1369077/best-implementaion-for-an-isnumberstring-method – StriplingWarrior Dec 05 '11 at 21:20
  • 13
    @MartijnCourteaux: "Throwing Exceptions doesn't reduce performance": False. "Regex will definitely be slower": True. – StriplingWarrior Dec 05 '11 at 21:21
  • http://stackoverflow.com/a/1486082/393908 – Ash Burlaczenko Dec 05 '11 at 21:22
  • 4
    @Martijn: throwing *lots* of exceptions can definitely be bad for performance (though I have a hard time coming up with a use case where you have to parse lots of data of which a large percentage is malformed). – Michael Borgwardt Dec 05 '11 at 21:23
  • 2
    @StriplingWarrior Actually you are incorrect. Throwing an Exception is not expensive, building the stack trace is. – Woot4Moo Dec 05 '11 at 21:23
  • "The performance penalty for throwing an exception is very small in a modern JVM if you don't print the stack trace." is a legitimate claim/ – Affe Dec 05 '11 at 21:23
  • 1
    @Woot4Moo: This answer indicates that it's roughly 66x slower than just doing a loop, without printing a stack trace. That may not be vastly slower once you take into account the cost of actually parsing the string, but it's not something to scoff at either. http://stackoverflow.com/a/299315/120955 – StriplingWarrior Dec 05 '11 at 21:31
  • IMHO this is not a duplicate. The question explicitly states a request for `bool int.TryParse(out string)` of which there is no implementation but it can be implemented. – Brett Ryan May 13 '16 at 02:57
  • Philosophizing....exceptions should be Exceptional. Thus when writing "routine" logic, that catches exceptions..seems horrible to me. – granadaCoder Nov 18 '20 at 21:52

3 Answers3

97

No. You have to make your own like this:

public int tryParseInt(String value, int defaultVal) {
    try {
        return Integer.parseInt(value);
    } catch (NumberFormatException e) {
        return defaultVal;
    }
}

...or

public Integer parseIntOrNull(String value) {
    try {
        return Integer.parseInt(value);
    } catch (NumberFormatException e) {
        return null;
    }
}
cambunctious
  • 8,391
  • 5
  • 34
  • 53
Woot4Moo
  • 23,987
  • 16
  • 94
  • 151
  • 8
    This doesn't return the parsed integer. How would they do that? – Ash Burlaczenko Dec 05 '11 at 21:23
  • 3
    You use that as a method to determine if it is safe to parse the int. Notice how the MSDN version also returns a boolean. – Woot4Moo Dec 05 '11 at 21:24
  • 1
    @AshBurlaczenko well this is Java and I used that as an analog. – Woot4Moo Dec 05 '11 at 21:38
  • 149
    So now we're not only adding the overhead of throwing and catching an exception, but we're also performing the actual parsing twice? – StriplingWarrior Dec 05 '11 at 22:34
  • For input validation this still makes sense. If you're passed a String that should be an int then this'd be nice. Especially since you use it with guava's: Preconditions.checkArgument(Integer.tryParse(par), "was expecting par to be int but was " + par) – Kurru Mar 29 '13 at 01:01
  • @StriplingWarrior: I agree... if you're going to parse the integer you may as well leave it up to the caller of `tryParseInt` to discard the result if it isn't necessary. – dreamlax Oct 07 '14 at 05:37
  • You can always use the dirty hack of using an object of the AtomicBoolean wrapper class as success output parameter, and returning the actual integer (or, on failure, a default value). – Nyerguds Jan 21 '15 at 09:53
  • 4
    The TryParse methods in C# use an "out" parameter (essentially a pointer) to set a target numeric variable IF the parse is successful, the success of which is indicated by the boolean return value of the method. Java does not have an equivalent to the out parameter, thus the need for the if logic shown in this answer. https://msdn.microsoft.com/en-us/library/f02979c7(v=vs.110).aspx – Peter Howe Nov 24 '15 at 14:42
  • 1
    Or use a default value... since, if we don't want an exception to take care of the problem, that's usually where we'll end up anyway. `tryParseInt(String value, int defaultValue)`. See Java 8's `Map.getOrDefault(...)` – Erk May 16 '18 at 15:34
  • I removed the example with the redundant parsing and the example with the hidden default value. Added a nullable version. – cambunctious Mar 17 '21 at 17:31
33

Apache Commons has an IntegerValidator class which appears to do what you want. Java provides no in-built method for doing this.

See here for the groupid/artifactid.

Code sample: (slightly verbose to show functionality clearly)

private boolean valueIsAndInt(String value) {
    boolean returnValue = true;
    if (null == new org.apache.commons.validator.routines.IntegerValidator().validate(value)) {
        returnValue = false;
    }
    return returnValue;
}
granadaCoder
  • 26,328
  • 10
  • 113
  • 146
Graham Borland
  • 60,055
  • 21
  • 138
  • 179
2

Edit -- just saw your comment about the performance problems associated with a potentially bad piece of input data. I don't know offhand how try/catch on parseInt compares to a regex. I would guess, based on very little hard knowledge, that regexes are not hugely performant, compared to try/catch, in Java.

Anyway, I'd just do this:

public Integer tryParse(Object obj) {
  Integer retVal;
  try {
    retVal = Integer.parseInt((String) obj);
  } catch (NumberFormatException nfe) {
    retVal = 0; // or null if that is your preference
  }
  return retVal;
}
Yuliia Ashomok
  • 8,336
  • 2
  • 60
  • 69
Jim Kiley
  • 3,632
  • 3
  • 26
  • 43
  • 42
    that is bad, 0 is an acceptable return value and is therefore impossible to deduce an exception or a valid entry. – Woot4Moo Dec 05 '11 at 21:21
  • Since you want to return Integer (instead of int) you could use the `new Integer(String)` constructor. – cherouvim Dec 05 '11 at 21:21
  • 4
    Exceptions are very slow, because they unwind the stack and look for any finally blocks. Exceptions should be avoided for validation. They are there for reporting serious problems, i.e. exceptions should be exceptional. – Concrete Gannet Aug 12 '12 at 06:36
  • An implementation of this with a default value parameter given to the function might be useful though. – Nyerguds Jan 21 '15 at 09:54
  • 3
    I think that returning null is the best approach as this more closely resembles the requested question of implementing `TryParse` which returns a boolean. To get around exceptions the `Integer.parseInt` implementation could be mirrored to return null instead of throwing `NumberFormatException`. – Brett Ryan May 13 '16 at 03:00
  • 3
    Also, the retVal is completely useless... – Oskar Hýbl Mar 28 '17 at 11:40
  • 2
    downvote. 0 is a valid integer – qwlice Nov 19 '18 at 13:39
  • 2
    @Woot4Moo *0 is an acceptable return value*... Depends. Depends on the problem domain. – Romeo Sierra Jun 19 '19 at 06:34