1

虽然这个问题很笼统,但我会提到引发查询的场景。

场景

我对分析大量字符串(尤其是数字字符串)感兴趣。因此,我的第一项工作是过滤掉那些甚至包含除数字以外的单个字符的那些。

一个简单的方法是(在 Java 中):

for (String val : stringArray){
   try{
     int num = Integer.parseInt(val);
     doSomething(num);
   }
   catch(NumberFormatException nfe){}
}

我必须提到的另一点是,数组中只有大约 5% 的字符串是纯数字的。因此,简而言之,将涉及很多捕捉。

我想知道的是,这在设计方面是否是一种有效的方式,还是我应该考虑其他方式来做同样的事情?


基于答案的结论:异常确实很昂贵,将它们用作控制语句的一种形式并不是一个很好的设计实践。因此,应该尽可能地尝试寻找替代方案,如果仍然有例外似乎更清晰/更容易,则应该将其记录好。

4

4 回答 4

2

您在此处所做的操作本质上是正确的,因为 java 中没有其他标准方法可以检查字符串是否为数字。

如果分析证明你这个操作太长了,你可以尝试像在 parseInt 方法中那样自己做,但是 JVM 不能做同样的优化,所以我不推荐它。您将看到 JVM 为处理异常进行了高度优化,并且它很好地完成了这项工作。

出于好奇,以下是在 java 中执行此操作的几种方法:

http://rosettacode.org/wiki/Determine_if_a_string_is_numeric#Java

带有指向其他语言的链接,但是您的解决方案是标准且惯用的解决方案,我怀疑您会像示例中那样重写它会发现很大的不同:

private static final boolean isNumeric(final String s) {
  if (s == null || s.isEmpty()) return false;
  for (int x = 0; x < s.length(); x++) {
    final char c = s.charAt(x);
    if (x == 0 && (c == '-')) continue;  // negative
    if ((c >= '0') && (c <= '9')) continue;  // 0 - 9
    return false; // invalid
  }
  return true; // valid
}

在我看来,使用它是过早优化导致代码可维护性降低的典型案例。

于 2012-06-15T15:34:14.210 回答
1

它效率不高。您可以在网上查找大量资源,了解为什么认为抛出异常很昂贵,例如:http ://www.yoda.arachsys.com/csharp/exceptions.html 。

不幸的是,Java 没有提供这样的实用方法 OOTB(如 C# 的 tryParse)。您可以枚举字符串的字符并使用 Character.isDigit 方法(您甚至可以将验证和转换交织成 int)。

异常应该用于某些流的异常终止。执行可能引发异常的操作时,您应该始终考虑是否可以执行检查以节省成本,尤其是处理异常的代码。例如 - 检查一个字符串是否是一个数字,而不是尝试解析它并依靠异常机制来告诉你它是否不是。

于 2012-06-15T15:42:11.817 回答
0

在您的应用程序的更大上下文中,这可能不太重要。像这样的微优化很难猜测。

更好的方法是尽可能简洁地编写代码,然后进行测量以查看其性能以及瓶颈所在的位置(如果有的话)。如果你发现自己的性能不能接受,找到最大的瓶颈,如果可以的话,解决它;冲洗并重复,直到性能可以接受。

问题是我们都不够聪明,无法“知道”问题出在哪里。你最好用数据优化而不是猜测。

在您的情况下,这是一个未经检查的异常。你可以忽略它,但这意味着一个坏字符串会把你吹出循环。将 catch 放在循环中允许您容忍一小部分输入字符串未能通过数字解析并继续。

于 2012-06-15T15:34:45.910 回答
0

检查纯数字字符串的一种基于非异常的方法是使用正则表达式。例如:

public static void main(String[] args) throws Exception {
    String[] array = {
            "abc",
            "123",
            "12A",
    };
    Pattern p = Pattern.compile("\\d*");
    for (String s: array) {
        Matcher m = p.matcher(s);
        if (m.matches()) {
            System.out.println(s);
        }
    }
}

基于异常的处理可能很昂贵。

正则表达式也不是最快的。

两者都试一下,看看哪个对你来说更快。

于 2012-06-15T15:38:16.110 回答