String的substring、split,外加StringTokenizer三者截取字符串...

最近在閱讀java.lang下的源碼,讀到String時,忽然想起面試的時候曾經被人問過:都知道在大數據量狀況下,使用String的split截取字符串效率很低,有想過用其餘的方法替代嗎?用什麼替代?我當時的回答很斬釘截鐵:沒有。java

google了一下,發現有2中替代方法,因而在這裏我將對這三種方式進行測試。面試

測試的軟件環境爲:Windows XP、eclipse、JDK1.6。正則表達式

測試用例使用類ip形式的字符串,即3位一組,使用」.」間隔。數據分別使用:5組、10組、100組、1000組、10000組、100000組。數組

實現

閒話不說,先上代碼:app

package test.java.lang.ref;

import java.util.Random;
import java.util.StringTokenizer;

/**
 * String測試類
 * 
 * 
 */
public class StringTest {

    public static void main(String args[]) {
        String orginStr = getOriginStr(10);

        // ////////////String.splic()表現//////////////////////////////////////////////
        System.out.println("使用String.splic()的切分字符串");
        long st1 = System.nanoTime();
        String[] result = orginStr.split("\\.");
        System.out.println("String.splic()截取字符串用時:" + (System.nanoTime() - st1));
        System.out.println("String.splic()截取字符串結果個數:" + result.length);
        System.out.println();

        // ////////////StringTokenizer表現//////////////////////////////////////////////
        System.out.println("使用StringTokenizer的切分字符串");
        long st3 = System.nanoTime();
        StringTokenizer token = new StringTokenizer(orginStr, ".");
        System.out.println("StringTokenizer截取字符串用時:" + (System.nanoTime() - st3));
        System.out.println("StringTokenizer截取字符串結果個數:" + token.countTokens());
        System.out.println();

        // //////////////////String.substring()表現//////////////////////////////////////////

        long st5 = System.nanoTime();
        int len = orginStr.lastIndexOf(".");
        System.out.println("使用String.substring()切分字符串");
        int k = 0, count = 0;

        for (int i = 0; i <= len; i++) {
            if (orginStr.substring(i, i + 1).equals(".")) {
                if (count == 0) {
                    orginStr.substring(0, i);
                } else {
                    orginStr.substring(k + 1, i);
                    if (i == len) {
                        orginStr.substring(len + 1, orginStr.length());
                    }
                }
                k = i;
                count++;
            }
        }
        System.out.println("String.substring()截取字符串用時" + (System.nanoTime() - st5));
        System.out.println("String.substring()截取字符串結果個數:" + (count + 1));
    }

    /**
     * 構造目標字符串 eg:10.123.12.154.154
     * 
     * @param len
     *            目標字符串組數(每組由3個隨機數組成)
     * @return
     */
    private static String getOriginStr(int len) {

        StringBuffer sb = new StringBuffer();
        StringBuffer result = new StringBuffer();
        Random random = new Random();
        for (int i = 0; i < len; i++) {
            sb.append(random.nextInt(9)).append(random.nextInt(9)).append(random.nextInt(9));
            result.append(sb.toString());
            sb.delete(0, sb.length());
            if (i != len - 1)
                result.append(".");
        }

        return result.toString();
    }
}

改變目標數據長度修改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源碼以下:

public String[] split(String regex, int limit) {
        return Pattern.compile(regex).split(this, limit);
    }

驗證可能存在不合理的地方,如哪裏不合適,還請指出,共同進步。

相關文章
相關標籤/搜索