在解析字符串之前,如何检查它是否是一个数字?
当前回答
这是我知道的最快的方法来检查字符串是否为数字:
public static boolean isNumber(String str){
int i=0, len=str.length();
boolean a=false,b=false,c=false, d=false;
if(i<len && (str.charAt(i)=='+' || str.charAt(i)=='-')) i++;
while( i<len && isDigit(str.charAt(i)) ){ i++; a=true; }
if(i<len && (str.charAt(i)=='.')) i++;
while( i<len && isDigit(str.charAt(i)) ){ i++; b=true; }
if(i<len && (str.charAt(i)=='e' || str.charAt(i)=='E') && (a || b)){ i++; c=true; }
if(i<len && (str.charAt(i)=='+' || str.charAt(i)=='-') && c) i++;
while( i<len && isDigit(str.charAt(i)) ){ i++; d=true;}
return i==len && (a||b) && (!c || (c && d));
}
static boolean isDigit(char c){
return c>='0' && c<='9';
}
其他回答
你可以使用java.util.Scanner对象。
public static boolean isNumeric(String inputData) {
Scanner sc = new Scanner(inputData);
return sc.hasNextInt();
}
这通常是通过一个简单的用户定义函数来完成的(例如,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();
}
我修改了CraigTP的解决方案,使其接受科学计数法,同时接受点和逗号作为小数分隔符
^-?\d+([,\.]\d+)?([eE]-?\d+)?$
例子
var re = new RegExp("^-?\d+([,\.]\d+)?([eE]-?\d+)?$");
re.test("-6546"); // true
re.test("-6546355e-4456"); // true
re.test("-6546.355e-4456"); // true, though debatable
re.test("-6546.35.5e-4456"); // false
re.test("-6546.35.5e-4456.6"); // false
异常开销很大,但在这种情况下,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);
}
}
使用IntStream并行检查非常长的字符串
在Java 8中,以下测试给定字符串的所有字符是否都在'0'到'9'之间。注意空字符串是被接受的:
string.chars().unordered().parallel().allMatch( i -> '0' <= i && '9' >= i )
推荐文章
- Java 8流和数组操作
- Java Regex捕获组
- 如何在Python中按字母顺序排序字符串中的字母
- Openssl不被视为内部或外部命令
- 如何添加自定义方法到Spring Data JPA
- 如何在Ubuntu中设置Java环境路径
- 无法执行dex:在Eclipse中超过GC开销限制
- 有人能解释一下JPA和Hibernate中的mappedBy吗?
- 是什么导致JNI调用变慢?
- Java中的&和&&有什么区别?
- 使用Java的Collections.singletonList()?
- python: SyntaxError: EOL扫描字符串文字
- PHP子字符串提取。获取第一个'/'之前的字符串或整个字符串
- Maven使用多个src目录编译
- 导入时无法解析符号