以下哪一项更好的做法是检查字符串是否浮动?
try{
Double.parseDouble(strVal);
}catch(NumberFormatException e){
//My Logic
}
或
if(!strVal.matches("[-+]?\\d*\\.?\\d+")){
//My Logic
}
在绩效,维护和可读性方面?
是的,我想知道哪一个是好编码练习?
答案 0 :(得分:4)
话虽这么说,我个人更喜欢第一个。性能是您希望在架构,数据结构设计等方面整体考虑的问题,而不是逐行考虑。衡量性能并优化实际上很慢的内容,而不是您认为可能很慢的内容。
答案 1 :(得分:4)
个人意见 - 我见过的代码,我希望大多数开发人员会倾向于尝试 - 捕获块。 try catch在某种意义上也更具可读性,并假设在大多数情况下字符串将包含有效数字。但是你可以考虑一些可能影响你选择的例子。
答案 2 :(得分:2)
当字符串与double匹配时,第一个将比正则表达式更好。例如,当识别器被硬编码时,解析它的速度非常快,就像使用Double.parse一样。此外,没有任何东西可以维护它,无论Java定义什么,因为Double是一个字符串。更不用说Double.parseDouble()更容易阅读。
另一个解决方案不会被编译,所以正则表达式必须要做的第一件事是编译和解析正则表达式,然后它必须运行该表达式,然后你必须执行Double.parseDouble( )把它变成双重的。对于传递给它的每个数字都要做到这一点。您可以使用Pattern.compile()对其进行优化,但执行表达式会变慢。特别是当您必须运行Double.doubleParse以将值转换为double时。
是的异常不是超快,但您只需在解析错误时支付该价格。如果你不打算看到很多错误,那么我不认为你会注意到在抛出时收集堆栈跟踪的速度变慢(这就是为什么异常表现不佳)。如果你只是遇到一些例外,那么性能不会成为问题。问题是你期望一个双倍,它可能不是一些配置错误所以告诉用户并退出,或选择一个合适的默认值并继续。在这些情况下,你就能做到这一切。
答案 3 :(得分:1)
如果您使用parseDouble
,您最终会得到Mark所说的内容,但会以更易读的方式,并且可能会从性能改进和错误修复中获益。
由于异常只会在抛出时成本高昂,因此只需要寻找不同的策略
最后你也会调用parseDouble,因此可以这样使用它。
请注意,您的模式拒绝7.作为Double,而Java和C / C ++没有,以及像4.2e8
这样的科学记数法。
答案 4 :(得分:1)
是的,我想知道哪一个是好编码练习?
根据具体情况,两者都可以是良好的编码实践。
如果不太可能出现不好的数字(即这是一种“异常”情况),那么基于异常的解决方案就可以了。 (实际上,如果错误数字的概率足够小,异常甚至可能平均更快。这取决于Double.parseDouble()
的相对速度和典型输入字符串的编译正则表达式。这需要进行测量。 。)
如果错误的数字合理(或非常)可能(即它不是“例外”情况),那么基于正则表达式的解决方案可能会更好。
如果执行测试的代码路径不经常执行,那么使用哪种方法确实没有区别。
答案 5 :(得分:1)
也许你也可以尝试这种方式。但这对包含有效数字的字符串来说是通用的。
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();
}
答案 6 :(得分:0)
以下是性能测试,以查看正则表达式VS try catch之间的性能差异,以验证字符串是否为数字。
下表显示了包含三个点(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<String> 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<String> getList(int count, int noiseCount) {
Random rand = new Random();
ArrayList<String> list = new ArrayList<String>();
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<String> list) {
ArrayList<Float> 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<String> list) {
ArrayList<Float> 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());
}
}