In my limited experience, I've been on several projects that have had some sort of string utility class with methods to determine if a given string is a number. The idea has always been the same, however, the implementation has been different. Some surround a parse attempt with try/catch
public boolean isInteger(String str) {
try {
Integer.parseInt(str);
return true;
} catch (NumberFormatException nfe) {}
return false;
}
and others match with regex
public boolean isInteger(String str) {
return str.matches("^-?[0-9]+(\\.[0-9]+)?$");
}
Is one of these methods better than the other? I personally prefer using the regex approach, as it's concise, but will it perform on par if called while iterating over, say, a list of a several hundred thousand strings?
Note: As I'm kinda new to the site I don't fully understand this Community Wiki business, so if this belongs there let me know, and I'll gladly move it.
EDIT: With all the TryParse suggestions I ported Asaph's benchmark code (thanks for a great post!) to C# and added a TryParse method. And as it seems, the TryParse wins hands down. However, the try catch approach took a crazy amount of time. To the point of me thinking I did something wrong! I also updated regex to handle negatives and decimal points.
Results for updated, C# benchmark code:
00:00:51.7390000 for isIntegerParseInt
00:00:03.9110000 for isIntegerRegex
00:00:00.3500000 for isIntegerTryParse
Using:
static bool isIntegerParseInt(string str) {
try {
int.Parse(str);
return true;
} catch (FormatException e){}
return false;
}
static bool isIntegerRegex(string str) {
return Regex.Match(str, "^-?[0-9]+(\\.[0-9]+)?$").Success;
}
static bool isIntegerTryParse(string str) {
int bob;
return Int32.TryParse(str, out bob);
}
I just ran some benchmarks on the performance of these 2 methods (On Macbook Pro OSX Leopard Java 6). ParseInt is faster. Here is the output:
This operation took 1562 ms.
This operation took 2251 ms.
And here is my benchmark code:
public class IsIntegerPerformanceTest {
public static boolean isIntegerParseInt(String str) {
try {
Integer.parseInt(str);
return true;
} catch (NumberFormatException nfe) {}
return false;
}
public static boolean isIntegerRegex(String str) {
return str.matches("^[0-9]+$");
}
public static void main(String[] args) {
long starttime, endtime;
int iterations = 1000000;
starttime = System.currentTimeMillis();
for (int i=0; i<iterations; i++) {
isIntegerParseInt("123");
isIntegerParseInt("not an int");
isIntegerParseInt("-321");
}
endtime = System.currentTimeMillis();
System.out.println("This operation took " + (endtime - starttime) + " ms.");
starttime = System.currentTimeMillis();
for (int i=0; i<iterations; i++) {
isIntegerRegex("123");
isIntegerRegex("not an int");
isIntegerRegex("-321");
}
endtime = System.currentTimeMillis();
System.out.println("This operation took " + (endtime - starttime) + " ms.");
}
}
Also, note that your regex will reject negative numbers and the parseInt method will accept them.
Here is our way of doing this:
public boolean isNumeric(String string) throws IllegalArgumentException
{
boolean isnumeric = false;
if (string != null && !string.equals(""))
{
isnumeric = true;
char chars[] = string.toCharArray();
for(int d = 0; d < chars.length; d++)
{
isnumeric &= Character.isDigit(chars[d]);
if(!isnumeric)
break;
}
}
return isnumeric;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With