在我有限的经验中,我参与了几个项目,这些项目有一些字符串实用程序类,其中包含确定给定字符串是否为数字的方法。这个想法一直都是一样的,然而,实施却有所不同。有些使用try / catch
包围解析尝试public boolean isInteger(String str) {
try {
Integer.parseInt(str);
return true;
} catch (NumberFormatException nfe) {}
return false;
}
和其他人匹配正则表达式
public boolean isInteger(String str) {
return str.matches("^-?[0-9]+(\\.[0-9]+)?$");
}
这些方法中的一种比另一种好吗?我个人更喜欢使用正则表达式方法,因为它很简洁,但是如果在迭代过程中调用,比如几十万个字符串的列表,它会在par上执行吗?
注意:由于我是网站的新手,我不完全理解这个社区Wiki业务,所以如果这属于那里,请告诉我,我很乐意移动它。
修改 有了所有的TryParse建议,我把Asaph的基准代码(感谢一个很棒的帖子!)移植到C#并添加了一个TryParse方法。而且看起来,TryParse赢得了胜利。然而,尝试捕获方法耗费了大量时间。我认为我做错了什么!我还更新了正则表达式来处理负数和小数点。
更新的C#基准代码的结果:
00:00:51.7390000 for isIntegerParseInt
00:00:03.9110000 for isIntegerRegex
00:00:00.3500000 for isIntegerTryParse
使用:
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);
}
答案 0 :(得分:13)
我刚刚对这两种方法的性能进行了一些基准测试(在Macbook Pro OSX Leopard Java 6上)。 ParseInt更快。这是输出:
This operation took 1562 ms.
This operation took 2251 ms.
这是我的基准代码:
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.");
}
}
另外,请注意您的正则表达式会拒绝负数,而parseInt方法会接受它们。
答案 1 :(得分:4)
以下是我们这样做的方法:
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;
}
答案 2 :(得分:3)
我需要重构像你这样的代码来摆脱NumberFormatException。重构的代码:
public static Integer parseInteger(final String str) {
if (str == null || str.isEmpty()) {
return null;
}
final Scanner sc = new Scanner(str);
return Integer.valueOf(sc.nextInt());
}
作为Java 1.4的人,我不知道 java.util.Scanner 。我找到了这篇有趣的文章:
http://rosettacode.org/wiki/Determine_if_a_string_is_numeric#Java
我个人喜欢使用扫描仪的解决方案,非常紧凑且仍然可读。
答案 3 :(得分:3)
如果绝对性能是关键,并且如果你只是检查整数(不是浮点数)我怀疑迭代字符串中的每个字符,如果遇到不在0-9范围内的某些字符,则返回false最快的。
RegEx是一种更通用的解决方案,因此对于特殊情况可能执行速度不快。抛出异常的解决方案在这种情况下会有一些额外的开销。如果您实际上并不关心数字的值,TryParse将会略微慢,只是它是否是一个数字,因为转换为数字也必须发生。
除了多次调用的内部循环外,所有这些选项之间的差异应该是微不足道的。
答案 4 :(得分:2)
如果你真的想简化它,我个人会这样做。
public boolean isInteger(string myValue)
{
int myIntValue;
return int.TryParse(myValue, myIntValue)
}
答案 5 :(得分:2)
您可以为字符串创建扩展方法,并使整个过程看起来更干净......
public static bool IsInt(this string str)
{
int i;
return int.TryParse(str, out i);
}
然后,您可以在实际代码中执行以下操作...
if(myString.IsInt())....
答案 6 :(得分:2)
有些语言,比如C#,有一个TryParse(或同等版本),对于类似的东西,效果相当不错。
public boolean IsInteger(string value)
{
int i;
return Int32.TryParse(value, i);
}
答案 7 :(得分:1)
使用.NET,您可以执行以下操作:
private bool isNumber(string str)
{
return str.Any(c => !char.IsDigit(c));
}
答案 8 :(得分:1)
public static boolean CheckString(String myString) {
char[] digits;
digits = myString.toCharArray();
for (char div : digits) {// for each element div of type char in the digits collection (digits is a collection containing div elements).
try {
Double.parseDouble(myString);
System.out.println("All are numbers");
return true;
} catch (NumberFormatException e) {
if (Character.isDigit(div)) {
System.out.println("Not all are chars");
return false;
}
}
}
System.out.println("All are chars");
return true;
}
答案 9 :(得分:1)
这是我的实现来检查字符串是否由数字组成:
public static boolean isNumeric(String string)
{
if (string == null)
{
throw new NullPointerException("The string must not be null!");
}
final int len = string.length();
if (len == 0)
{
return false;
}
for (int i = 0; i < len; ++i)
{
if (!Character.isDigit(string.charAt(i)))
{
return false;
}
}
return true;
}
答案 10 :(得分:1)
我喜欢代码:
public static boolean isIntegerRegex(String str) {
return str.matches("^[0-9]+$");
}
但在使用它之前创建模式会更好:
public static Pattern patternInteger = Pattern.compile("^[0-9]+$");
public static boolean isIntegerRegex(String str) {
return patternInteger.matcher(str).matches();
}
通过测试申请我们有结果:
This operation isIntegerParseInt took 1313 ms.
This operation isIntegerRegex took 1178 ms.
This operation isIntegerRegexNew took 304 ms.
使用:
public class IsIntegerPerformanceTest {
private static Pattern pattern = Pattern.compile("^[0-9]+$");
public static boolean isIntegerParseInt(String str) {
try {
Integer.parseInt(str);
return true;
} catch (NumberFormatException nfe) {
}
return false;
}
public static boolean isIntegerRegexNew(String str) {
return pattern.matcher(str).matches();
}
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 isIntegerParseInt 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 isIntegerRegex " + (endtime - starttime) + " ms.");
starttime = System.currentTimeMillis();
for (int i = 0; i < iterations; i++) {
isIntegerRegexNew("123");
isIntegerRegexNew("not an int");
isIntegerRegexNew("-321");
}
endtime = System.currentTimeMillis();
System.out.println("This operation took isIntegerRegexNew " + (endtime - starttime) + " ms.");
}
}
答案 11 :(得分:1)
我认为如果您执行以下操作(Java),它可能比以前的解决方案更快:
public final static boolean isInteger(String in)
{
char c;
int length = in.length();
boolean ret = length > 0;
int i = ret && in.charAt(0) == '-' ? 1 : 0;
for (; ret && i < length; i++)
{
c = in.charAt(i);
ret = (c >= '0' && c <= '9');
}
return ret;
}
我运行了Asaph运行的相同代码,结果是:
此操作耗时28毫秒。
一个巨大的差异(在我的电脑上,1691毫秒和2049毫秒)。请注意,此方法不验证字符串是否为空,因此您应该先执行此操作(包括字符串修剪)
答案 12 :(得分:1)
我认为这里的人们错过了一点。重复使用相同的模式具有非常容易的优化。只需使用模式的单例。这样做,在我的所有测试中,try-catch方法永远不会比模式方法有更好的基准。通过成功测试,try-catch需要两倍的时间,失败测试的速度要慢6倍。
public static final Pattern INT_PATTERN= Pattern.compile("^-?[0-9]+(\\.[0-9]+)?$");
public static boolean isInt(String s){
return INT_PATTERN.matcher(s).matches();
}
答案 13 :(得分:0)
我使用这个,但我喜欢Asaph在帖子中的严谨性。
public static bool IsNumeric(object expression)
{
if (expression == null)
return false;
double number;
return Double.TryParse(Convert.ToString(expression, CultureInfo.InvariantCulture), NumberStyles.Any,
NumberFormatInfo.InvariantInfo, out number);
}
答案 14 :(得分:0)
对于长数字使用此: (JAVA)
public static boolean isNumber(String string) {
try {
Long.parseLong(string);
} catch (Exception e) {
return false;
}
return true;
}
答案 15 :(得分:0)
public static boolean isNumber(String str){
return str.matches("[0-9]*\\.[0-9]+");
}
检查数字是否(包括浮点数,整数)
答案 16 :(得分:0)
我之前回答的修改版本:
public static boolean isInteger(String in)
{
if (in != null)
{
char c;
int i = 0;
int l = in.length();
if (l > 0 && in.charAt(0) == '-')
{
i = 1;
}
if (l > i)
{
for (; i < l; i++)
{
c = in.charAt(i);
if (c < '0' || c > '9')
return false;
}
return true;
}
}
return false;
}
答案 17 :(得分:0)
我刚把这个类添加到我的utils:
public class TryParseLong {
private boolean isParseable;
private long value;
public TryParseLong(String toParse) {
try {
value = Long.parseLong(toParse);
isParseable = true;
} catch (NumberFormatException e) {
// Exception set to null to indicate it is deliberately
// being ignored, since the compensating action
// of clearing the parsable flag is being taken.
e = null;
isParseable = false;
}
}
public boolean isParsable() {
return isParseable;
}
public long getLong() {
return value;
}
}
使用它:
TryParseLong valueAsLong = new TryParseLong(value);
if (valueAsLong.isParsable()) {
...
// Do something with valueAsLong.getLong();
} else {
...
}
这只解析一次值。
它仍然通过异常使用异常和控制流,但至少它将这种代码封装在实用程序类中,使用它的代码可以更正常的方式工作。
Java与C#的问题在于C#具有值并通过引用传递,因此它可以有效地返回2条信息;指示某些内容是否可解析的标志,以及实际解析的值。当我们在Java中重新生成&gt; 1值时,我们需要创建一个对象来保存它们,所以我采用了这种方法并将标记和解析后的值放在一个对象中。
转义分析可能会有效地处理这个问题,并在堆栈上创建值和标志,并且永远不会在堆上创建此对象,因此我认为这样做对性能的影响很小。
根据我的想法,这给出了在保持控制流异常的代码,良好的性能以及不多次解析整数之间的最佳折衷。
答案 18 :(得分:0)
public static boolean CheckIfNumber(String number){
for(int i = 0; i < number.length(); i++){
try{
Double.parseDouble(number.substring(i));
}catch(NumberFormatException ex){
return false;
}
}
return true;
}
之前我遇到过这个问题,但是当我输入一个数字然后输入一个字符时,它仍然会返回true,我认为这是更好的方法。只需检查每个字符是否都是数字。如果你有一个用户输入&#34; 1abc&#34;的情况需要更长时间。出于某种原因,当我试图在没有迭代的情况下尝试捕获时,它仍然认为它是一个数字...