最近在閱讀java.lang下的源碼,讀到String時,忽然想起面試的時候曾經被人問過:都知道在大數據量狀況下,使用String的split截取字符串效率很低,有想過用其餘的方法替代嗎?用什麼替代?我當時的回答很斬釘截鐵:沒有。java
google了一下,發現有2中替代方法,因而在這裏我將對這三種方式進行測試。面試
測試的軟件環境爲:Windows XP、eclipse、JDK1.6。正則表達式
測試用例使用類ip形式的字符串,即3位一組,使用」.」間隔。數據分別使用:5組、10組、100組、1000組、10000組、100000組。數組
閒話不說,先上代碼:app
1 package test.java.lang.ref; 2 3 import java.util.Random; 4 import java.util.StringTokenizer; 5 6 /** 7 * String測試類 8 * @author xiaori.Liu 9 * 10 */ 11 public class StringTest { 12 13 public static void main(String args[]){ 14 String orginStr = getOriginStr(10); 15 16 //////////////String.splic()表現////////////////////////////////////////////// 17 System.out.println("使用String.splic()的切分字符串"); 18 long st1 = System.nanoTime(); 19 String [] result = orginStr.split("\\."); 20 System.out.println("String.splic()截取字符串用時:" + (System.nanoTime()-st1)); 21 System.out.println("String.splic()截取字符串結果個數:" + result.length); 22 System.out.println(); 23 24 //////////////StringTokenizer表現////////////////////////////////////////////// 25 System.out.println("使用StringTokenizer的切分字符串"); 26 long st3 = System.nanoTime(); 27 StringTokenizer token=new StringTokenizer(orginStr,"."); 28 System.out.println("StringTokenizer截取字符串用時:"+(System.nanoTime()-st3)); 29 System.out.println("StringTokenizer截取字符串結果個數:" + token.countTokens()); 30 System.out.println(); 31 32 ////////////////////String.substring()表現////////////////////////////////////////// 33 34 35 long st5 = System.nanoTime(); 36 int len = orginStr.lastIndexOf("."); 37 System.out.println("使用String.substring()切分字符串"); 38 int k=,count=; 39 40 for (int i = ; i <= len; i++) { 41 if(orginStr.substring(i, i+1).equals(".")){ 42 if(count==){ 43 orginStr.substring(, i); 44 }else{ 45 orginStr.substring(k+1, i); 46 if(i == len){ 47 orginStr.substring(len+1, orginStr.length()); 48 } 49 } 50 k=i;count++; 51 } 52 } 53 System.out.println("String.substring()截取字符串用時"+(System.nanoTime()-st5)); 54 System.out.println("String.substring()截取字符串結果個數:" + (count + 1)); 55 } 56 57 /** 58 * 構造目標字符串 59 * eg:10.123.12.154.154 60 * @param len 目標字符串組數(每組由3個隨機數組成) 61 * @return 62 */ 63 private static String getOriginStr(int len){ 64 65 StringBuffer sb = new StringBuffer(); 66 StringBuffer result = new StringBuffer(); 67 Random random = new Random(); 68 for(int i = ; i < len; i++){ 69 sb.append(random.nextInt(9)).append(random.nextInt(9)).append(random.nextInt(9)); 70 result.append(sb.toString()); 71 sb.delete(, sb.length()); 72 if(i != len-1) 73 result.append("."); 74 } 75 76 return result.toString(); 77 } 78 }
改變目標數據長度修改getOriginStr的len參數便可。dom
5組測試數據結果以下圖:eclipse
下面這張圖對比了下,split耗時爲substring和StringTokenizer耗時的倍數:性能
好吧,我又花了點兒時間,作了幾張圖表來分析這3中方式的性能。測試
首先來一張柱狀圖對比一下這5組數據截取所花費的時間:大數據
從上圖能夠看出StringTokenizer的性能實在是太好了(對比另兩種),幾乎在圖表中看不見它的身影。遙遙領先。substring花費的時間始終比split要少,可是耗時也在隨着數據量的增長而增長。
下面3張折線圖能夠很明顯看出split、substring、StringTokenizer3中實現隨着數據量增長,耗時的趨勢。
split是變化最大的,也就是數據量越大,截取所須要的時間增加越快。
substring則比split要平穩一點點,可是也在增加。
StringTokenizer則是表現最優秀的,基本上平穩,始終保持在5000ns一下。
最終,StringTokenizer在截取字符串中效率最高,不論數據量大小,幾乎持平。substring則要次之,數據量增長耗時也要隨之增長。split則是表現最差勁的。
究其緣由,split的實現方式是採用正則表達式實現,因此其性能會比較低。至於正則表達式爲什麼低,還未去驗證。split源碼以下:
1 public String[] split(String regex, int limit) { 2 return Pattern.compile(regex).split(this, limit); 3 }
驗證可能存在不合理的地方,如哪裏不合適,還請指出,共同進步。