在解析字符串之前,如何检查它是否是一个数字?
当前回答
谷歌的Guava库提供了一个很好的辅助方法:你可以像使用Integer一样使用它。parseInt,但如果字符串没有解析为有效整数,它将返回null而不是抛出异常。注意,它返回的是Integer,而不是int,所以你必须将它转换/自动装箱回int。
例子:
String s1 = "22";
String s2 = "22.2";
Integer oInt1 = Ints.tryParse(s1);
Integer oInt2 = Ints.tryParse(s2);
int i1 = -1;
if (oInt1 != null) {
i1 = oInt1.intValue();
}
int i2 = -1;
if (oInt2 != null) {
i2 = oInt2.intValue();
}
System.out.println(i1); // prints 22
System.out.println(i2); // prints -1
但是,在当前发行版(Guava r11)中,它仍然被标记为@Beta。
我还没有对它进行基准测试。查看源代码,有一些开销来自大量的完整性检查,但最终他们使用Character.digit(string.charAt(idx)),类似,但略有不同,从@Ibrahim上面的答案。在它们的实现中没有异常处理开销。
其他回答
这通常是通过一个简单的用户定义函数来完成的(例如,roll your-own的“isNumeric”函数)。
喜欢的东西:
public static boolean isNumeric(String str) {
try {
Double.parseDouble(str);
return true;
} catch(NumberFormatException e){
return false;
}
}
然而,如果您经常调用这个函数,并且由于不是一个数字,您希望许多检查失败,那么这种机制的性能就不会很好,因为您依赖于每次失败都会抛出异常,这是一个相当昂贵的操作。
另一种方法可能是使用正则表达式来检查是否是一个数字:
public static boolean isNumeric(String str) {
return str.matches("-?\\d+(\\.\\d+)?"); //match a number with optional '-' and decimal.
}
但是要小心上面的RegEx机制,因为如果你使用非阿拉伯数字(即0到9以外的数字),它会失败。这是因为RegEx的“\d”部分只匹配[0-9],并且有效地不具有国际数字意识。(感谢OregonGhost指出这一点!)
甚至另一种替代方法是使用Java内置的Java .text. numberformat对象来查看解析字符串后解析器的位置是否位于字符串的末尾。如果是,我们可以假设整个字符串都是数字:
public static boolean isNumeric(String str) {
ParsePosition pos = new ParsePosition(0);
NumberFormat.getInstance().parse(str, pos);
return str.length() == pos.getIndex();
}
异常开销很大,但在这种情况下,RegEx需要更长的时间。下面的代码显示了两个函数的简单测试——一个使用异常,一个使用正则表达式。在我的机器上,RegEx版本比异常慢10倍。
import java.util.Date;
public class IsNumeric {
public static boolean isNumericOne(String s) {
return s.matches("-?\\d+(\\.\\d+)?"); //match a number with optional '-' and decimal.
}
public static boolean isNumericTwo(String s) {
try {
Double.parseDouble(s);
return true;
} catch (Exception e) {
return false;
}
}
public static void main(String [] args) {
String test = "12345.F";
long before = new Date().getTime();
for(int x=0;x<1000000;++x) {
//isNumericTwo(test);
isNumericOne(test);
}
long after = new Date().getTime();
System.out.println(after-before);
}
}
你可以使用NumberFormat#parse:
try
{
NumberFormat.getInstance().parse(value);
}
catch(ParseException e)
{
// Not a number.
}
在Apache Commons Lang 3.5及以上版本中:NumberUtils。isCreatable或StringUtils.isNumeric。
使用Apache Commons Lang 3.4及以下版本:NumberUtils。isNumber或StringUtils.isNumeric。
你也可以使用StringUtils。isNumericSpace对于空字符串返回true,忽略字符串中的内部空格。另一种方法是使用NumberUtils。isParsable,根据Java检查数字是否可解析。(链接的javadocs包含每种方法的详细示例。)
一个有效的方法避免尝试捕获和处理负数和科学符号。
Pattern PATTERN = Pattern.compile( "^(-?0|-?[1-9]\\d*)(\\.\\d+)?(E\\d+)?$" );
public static boolean isNumeric( String value )
{
return value != null && PATTERN.matcher( value ).matches();
}
推荐文章
- 在流中使用Java 8 foreach循环移动到下一项
- 访问限制:'Application'类型不是API(必需库rt.jar的限制)
- 用Java计算两个日期之间的天数
- 如何配置slf4j-simple
- Printf与std::字符串?
- 在Jar文件中运行类
- 带参数的可运行?
- 不区分大小写的“in”
- 我如何得到一个字符串的前n个字符而不检查大小或出界?
- 我可以在Java中设置enum起始值吗?
- Java中的回调函数
- 如何在PHP中截断字符串最接近于一定数量的字符?
- c#和Java中的泛型有什么不同?和模板在c++ ?
- 在Java中,流相对于循环的优势是什么?
- Jersey在未找到InjectionManagerFactory时停止工作