最近看了几本关于JAVA编程效率优化的数,感触颇多。刚好做到一个地方需要验证是否为数字(小数),Google了几个方法进行了比较和改进:
测试代码:
public static boolean isNumeric1(String str) {
for (int i = str.length(); --i >= 0;) {
if (!Character.isDigit(str.charAt(i))) {
return false;
}
}
return true;
}
public static boolean isNumeric2(String str) {
Pattern pattern = Pattern.compile("[0-9]*");
return pattern.matcher(str).matches();
}
public static boolean isNumeric3(String str) {
if (str.matches("\\d*")) {
return true;
} else {
return false;
}
}
public static boolean isNumeric4(String str) {
for (int i = str.length(); --i >= 0;) {
int chr = str.charAt(i);
if (chr < 48 || chr > 57)
return false;
}
return true;
}
/**
* @param args
*/
public static void main(String[] args) {
long s1 = System.currentTimeMillis();
for (int i = 0; i < 1000000; i++) {
test.isNumeric1("1111111111111111111111111111111111111111111111d");
}
long s2 = System.currentTimeMillis();
System.out.println("isNumeric1:" + (s2 - s1));
for (int i = 0; i < 1000000; i++) {
test.isNumeric2("1111111111111111111111111111111111111111111111d");
}
long s3 = System.currentTimeMillis();
System.out.println("isNumeric2:" + (s3 - s2));
for (int i = 0; i < 1000000; i++) {
test.isNumeric3("1111111111111111111111111111111111111111111111d");
}
long s4 = System.currentTimeMillis();
System.out.println("isNumeric3:" + (s4 - s3));
for (int i = 0; i < 1000000; i++) {
test.isNumeric4("1111111111111111111111111111111111111111111111d");
}
long s5 = System.currentTimeMillis();
System.out.println("isNumeric4:" + (s5 - s4));
for (int i = 0; i < 1000000; i++) {
org.apache.commons.lang.StringUtils.isNumeric("1111111111111111111111111111111111111111111111d");
}
long s6 = System.currentTimeMillis();
System.out.println("isNumeric5:" + (s6 - s5));
}
测试结果:
isNumeric1:42
isNumeric2:1614
isNumeric3:1355
isNumeric4:27
isNumeric5:195
看起来isNumeric4胜出较多,但是先别下结论,将测试数据改为d111111111111111111111111111111111111111111111结果如下:
isNumeric1:65
isNumeric2:1305
isNumeric3:1087
isNumeric4:42
isNumeric5:104
虽然优势不那么明显但还是isNumeric4胜出
改进:isNumeric4虽然快,但也只能分析正整数,因此调整其为:
public static boolean isNumeric4(String str) {
boolean flag = true;
int length = str.length();
for (int i = length; --i >= 0;) {
int chr = str.charAt(i);
if (chr < 48 || chr > 57) {
if (i == 0 && (chr == 45 || chr == 43)) {
continue;
} else if (i != length -1 && i != 0 && (flag && chr == 46)) {
flag = false;
continue;
} else {
return false;
}
}
}
return true;
}
这样就可以基本识别小数并且最前面可以带“+”、“-”,再进行两次测试:
字符串为:1111111111111111111111111111111111111111111111d
isNumeric1:44
isNumeric2:1586
isNumeric3:1763
isNumeric4:38
isNumeric5:178
字符串为:d1111111111111111111111111111111111111111111111
isNumeric1:146
isNumeric2:1034
isNumeric3:672
isNumeric4:212
isNumeric5:98
可见使用第二种字符串测试其性能低于了isNumeric1,但在功能上这点牺牲还是可以接受的。
虽然使用了超多次循环来测试,但每次的测试数据还是不能统一,可能和java虚拟机不同时候的性能有关系,所以这里只对同次测试的数据进行比较。
结论:考虑到各种情况,最优效率是将验证整数和整数(小数)分开,在能够判确认的情况下尽量使用整数验证。