正则表达式或exception处理?

以下哪一项更好的做法是检查字符串是否浮动?

try{ Double.parseDouble(strVal); }catch(NumberFormatException e){ //My Logic } 

要么

 if(!strVal.matches("[-+]?\\d*\\.?\\d+")){ //My Logic } 

在性能,维护和可读性方面?

是的,我想知道哪一个是好编码练习?

个人观点 – 我见过的代码,我希望大多数开发人员倾向于尝试 – 捕获块。 try catch在某种意义上也更具可读性,并假设在大多数情况下字符串将包含有效数字。 但是有很多事情要考虑你可以影响你选择的例子。

  1. 您希望字符串多久不包含有效数字。
  2. 请注意,对于批量处理,您应该在循环外部创建Pattern对象。 这将阻止代码每次都重新编译模式。
  3. 作为一般规则,您绝不应将期望用作逻辑流程。 你的try-catch表示逻辑,如果它不是一个字符串,你的正则表达式表示逻辑,如果它是一个数字。 所以代码的上下文是什么并不明显。
  4. 如果你选择正则表达式技术,你可能仍然需要在某个时候转换,所以实际上,这可能是浪费精力。
  5. 最后,应用程序的性能要求是否足够重要,以保证在此级别进行分析。 一般来说,我建议保持尽可能简单,使其工作,然后如果存在性能问题,使用一些代码分析工具找到瓶颈并调整它们。
  1. 性能:exception很慢,基于exception的逻辑也是如此,所以第二个会更快。
  2. 维护/可靠性:第一个是清晰的,并将随Java Framework的更新保持更新。

话虽如此,我个人更喜欢第一个。 性能是您希望在架构,数据结构设计等方面整体考虑的问题,而不是逐行考虑。 衡量性能并优化实际上很慢的内容,而不是您认为可能很慢的内容。

当字符串与double匹配时,第一个将比正则表达式更好。 例如,当识别器被硬编码时,解析它的速度非常快,就像使用Double.parse一样。 此外,没有任何东西可以维护它,无论Java定义什么,因为Double是一个字符串。 更不用说Double.parseDouble()更容易阅读。

另一个解决方案不会被编译,所以正则表达式必须要做的第一件事是编译和解析regex表达式,然后它必须运行该表达式,然后你必须执行Double.parseDouble()来获取它成了一个双。 对于传递给它的每个数字都要做到这一点。 您可以使用Pattern.compile()对其进行优化,但执行表达式会更慢。 特别是当您必须运行Double.doubleParse以将值转换为double时。

是例外并不是超快,但您只需在解析错误时支付该价格。 如果你不打算看到很多错误,那么我认为你不会注意到在抛出时收集堆栈跟踪的速度变慢(这就是exception执行效果不佳的原因)。 如果你只是遇到一些例外,那么性能不会成为问题。 问题是你期望一个双倍,它可能不是一些配置错误所以告诉用户并退出,或选择一个合适的默认值并继续。 这就是你在这些情况下所能做的一切。

如果你使用parseDouble ,你将最终得到Mark所说的,但是以更易读的方式,并且可能从性能改进和错误修复中获益。

由于exception在抛出时成本很高,因此只需要寻找不同的策略

  • 期望错误的格式经常发生
  • 期望它们落入一种特定的模式,你可以更快地捕获它

最后你也会调用parseDouble,因此可以这样使用它。

请注意,您的模式拒绝7.作为Double,而Java和C / C ++没有,以及4.2e8等科学记数法。

也许你也可以尝试这种方式。但这对于包含有效数字的字符串是通用的。

 public static boolean isNumeric(String str) { str = "2.3452342323423424E8"; // str = "21414124.12412412412412"; // str = "123123"; NumberFormat formatter = NumberFormat.getInstance(); ParsePosition pos = new ParsePosition(0); formatter.parse(str, pos); return str.length() == pos.getIndex(); } 

是的,我想知道哪一个是好编码练习?

根据具体情况,要么是良好的编码实践。

  • 如果不太可能出现不好的数字(即它是一个“例外”情况),那么基于exception的解决方案就没问题了。 (实际上,如果错误数字的概率足够小,exception甚至可能平均更快。这取决于Double.parseDouble()的相对速度和典型输入字符串的编译正则表达式。这需要进行测量。 。)

  • 如果坏数字合理(或非常)可能(即它不是“特殊”情况),那么基于正则表达式的解决方案可能更好。

  • 如果执行测试的代码路径不经常执行,那么使用哪种方法确实没有区别。

下面是性能测试,以查看正则表达式VS try catch之间的性能差异,以validation字符串是否为数字。

下表显示了包含三个点(90%,70%,50%)良好数据(浮点值)和剩余不良数据(字符串)的列表(100k)的统计数据。

  **90% - 10% 70% - 30% 50% - 50%** **Try Catch** 87234580 122297750 143470144 **Regular Expression** 202700266 192596610 162166308 

try catch的性能更好(除非坏数据超过50%),即使try / catch可能对性能有一些影响。 try catch的性能影响是因为try / catch阻止JVM进行一些优化。 Joshua Bloch在“Effective Java”中说过以下内容: Joshua Bloch在“Effective Java”中说过以下内容:

•将代码放在try-catch块中会禁止现有JVM实现可能执行的某些优化。

 public class PerformanceStats { static final String regularExpr = "([0-9]*[.])?[0-9]+"; public static void main(String[] args) { PerformanceStats ps = new PerformanceStats(); ps.statsFinder(); //System.out.println("123".matches(regularExpr)); } private void statsFinder() { int count = 200000; int ncount = 200000; ArrayList ar = getList(count, ncount); System.out.println("count = " + count + " ncount = " + ncount); long t1 = System.nanoTime(); validateWithCatch(ar); long t2 = System.nanoTime(); validateWithRegularExpression(ar); long t3 = System.nanoTime(); System.out.println("time taken with Exception " + (t2 - t1) ); System.out.println("time taken with Regular Expression " + (t3 - t2) ); } private ArrayList getList(int count, int noiseCount) { Random rand = new Random(); ArrayList list = new ArrayList(); for (int i = 0; i < count; i++) { list.add((String) ("" + Math.abs(rand.nextFloat()))); } // adding noise for (int i = 0; i < (noiseCount); i++) { list.add((String) ("sdss" + rand.nextInt() )); } return list; } private void validateWithRegularExpression(ArrayList list) { ArrayList ar = new ArrayList<>(); for (String s : list) { if (s.matches(regularExpr)) { ar.add(Float.parseFloat(s)); } } System.out.println("the size is in regular expression " + ar.size()); } private void validateWithCatch(ArrayList list) { ArrayList ar = new ArrayList<>(); for (String s : list) { try { float e = Float.parseFloat(s); ar.add(e); } catch (Exception e) { } } System.out.println("the size is in catch block " + ar.size()); } 

}