欢迎进入Java社区论坛,与200万技术人员互动交流 >>进入
新的pack方法和旧的实现差不太多–把一个字符串转化成一个尽可能小的Character/Integer/Long/Double/String类型,使得result.toString()。equals(orginalString)为true.
<BR>public static Object strToObject( final String str )
<BR>{
<BR> if ( str == null || str.length() > 17 )
<BR> { //out of Long range
<BR> return str;
<BR> }
<BR> if ( str.equals( “” ) )
<BR> return “”; //ensure interned string is returned
<BR> if ( str.length() == 1 )
<BR> return str.charAt( 0 ); //return Character
<BR> //if starts with zero – support only “0” and “0.something”
<BR> if ( str.charAt( 0 ) == ‘0’ )
<BR> {
<BR> if ( str.equals( “0” ) )
<BR> return 0;
<BR> if ( !str.startsWith( “0.” ) ) //this may be a double
<BR> return str;
<BR> }
<BR>
<BR> long res = 0;
<BR> int sign = 1;
<BR> for ( int i = 0; i < str.length(); ++i )
<BR> {
<BR> final char c = str.charAt( i );
<BR> if ( c <= ‘9’ && c >= ‘0’ )
<BR> res = res * 10 + ( c – ‘0’ );
<BR> else if ( c == ‘.’ )
<BR> {
<BR> //too lazy to write a proper Double parser, use JDK one
<BR> try
<BR> {
<BR> final Double val = Double.valueOf( str );
<BR> //check if value converted back to string equals to an original string
<BR> final String reverted = val.toString();
<BR> return reverted.equals( str ) ? val : str;
<BR> }
<BR> catch ( NumberFormatException ex )
<BR> {
<BR> return str;
<BR> }
<BR> }
<BR> else if ( c == ‘-‘ )
<BR> {
<BR> if ( i == 0 )
<BR> sign = -1; //switch sign at first position
<BR> else
<BR> return str; //otherwise it is not numeric
<BR> }
<BR> else if ( c == ‘+’ )
<BR> {
<BR> if ( i == 0 )
<BR> sign = 1; //sign at first position
<BR> else
<BR> return str; //otherwise it is not numeric
<BR> }
<BR> else //non-numeric
<BR> return str;
<BR> }
<BR> //cast to int if value is in int range
<BR> if ( res < Integer.MAX_VALUE )
<BR> return ( int ) res * sign;
<BR> //otherwise return Long
<BR> return res * sign;
<BR>}
<BR>
很惊讶吧,新的方法解析数字比JDK的实现快多了!很大一个原因是因为JDK在解析的最后,调用了一个支持的解析方法,像这样:
public static int parseInt( String s, int radix ) throws NumberFormatException
新的方法和旧的相比(注意方法调用的次数–对于非数字串pack只调用了1百万次,而别的情况能调用到千万级别):
<BR>Pack: Made 100.000.000 iterations for string ‘12345’ : time = 12.145 sec
<BR>Pack: Made 1.000.000 iterations for string ‘12345a’ : time = 23.248 sec
<BR>strToObject: Made 100.000.000 iterations for string ‘12345’ : time = 6.311 sec
<BR>strToObject: Made 100.000.000 iterations for string ‘12345a’ : time = 5.807 sec
<BR>
总结
千万不要把异常当成返回码一样用,或者当作可能发生的事件(尤其是和IO无关的方法)往外抛。抛异常的代价太昂贵了,对于一般的方法,至少要慢百倍以上。
如果你每条数据都需要解析,又经常会出现非数值串的时候,尽量不要用Number子类型的parse*/valueOf这些方法。为了性能考虑,你应当手动解析它们。
[1][2]
幸福就是重复。每天跟自己喜欢的人一起,