在解析字符串之前,如何检查它是否是一个数字?


当前回答

异常开销很大,但在这种情况下,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);

}

}

其他回答

异常开销很大,但在这种情况下,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);

}

}

在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包含每种方法的详细示例。)

这通常是通过一个简单的用户定义函数来完成的(例如,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();
}
public static boolean isNumeric(String str)
{
    return str.matches("-?\\d+(.\\d+)?");
}

CraigTP的正则表达式(如上所示)会产生一些误报。如。"23y4"将被算作一个数字,因为'。'匹配任何字符,而不是小数点。

此外,它将拒绝任何以“+”开头的数字

避免这两个小问题的替代方法是

public static boolean isNumeric(String str)
{
    return str.matches("[+-]?\\d*(\\.\\d+)?");
}

这是一个简单的检查示例:

public static boolean isNumericString(String input) {
    boolean result = false;

    if(input != null && input.length() > 0) {
        char[] charArray = input.toCharArray();

        for(char c : charArray) {
            if(c >= '0' && c <= '9') {
                // it is a digit
                result = true;
            } else {
                result = false;
                break;
            }
        }
    }

    return result;
}