當前位置:才華齋>IT認證>SUN認證>

關於JAVA字串的拼接與效能

SUN認證 閱讀(1.09W)

在JAVA中拼接兩個字串的最簡便的方式就是使用操作符”+”了。如果你用”+”來連線固定長度的字串,可能效能上會稍受影響,但是如果你是在迴圈中來”+”多個串的話,效能將指數倍的下降。假設有一個字串,我們將對這個字串做大量迴圈拼接操作,使用”+”的話將得到最低的效能。但是究竟這個效能有多差?下面小編準備了關於JAVA字串的拼接與效能,提供給大家參考!

關於JAVA字串的拼接與效能

我們將使用Per4j來計算效能,因為這個工具可以給我們一個完整的效能指標集合,比如最小,最大耗時,統計時間段的標準偏差等。在測試程式碼中,為了得到一個準確的標準偏差值,我們將執行20個拼接”*”50,000次的測試。下面是我們將使用到的拼接字串的方法:

Concatenation Operator (+)

String concat method – concat(String str)

StringBuffer append method – append(String str)

StringBuilder append method – append(String str)

最後,我們將看看位元組碼,來研究這些方法到底是如何執行的。現在,讓我們先開始來建立我捫的類。注意為了計算每個迴圈的效能,程式碼中的每段測試程式碼都需要用Per4J庫進行封裝。首先我們先定義迭代次數

1 private static final int OUTER_ITERATION=20;

2 private static final int INNER_ITERATION=50000;

接下來,我們將使用上述4個方法來實現我們的測試程式碼。

01 String addTestStr = "";

02 String concatTestStr = "";

03 StringBuffer concatTestSb = null;

04 StringBuilder concatTestSbu = null;

05 for (int outerIndex=0;outerIndex<=OUTER_ITERATION;outerIndex++) {

06 StopWatch stopWatch = new LoggingStopWatch("StringAddConcat");

07 addTestStr = "";

08 for (int innerIndex=0;innerIndex<=INNER_ITERATION;innerIndex++)

09 addTestStr += "*";

10 ();

11 }

12 for (int outerIndex=0;outerIndex<=OUTER_ITERATION;outerIndex++) {

13 StopWatch stopWatch = new LoggingStopWatch("StringConcat");

14 concatTestStr = "";

15 for (int innerIndex=0;innerIndex<=INNER_ITERATION;innerIndex++)

16 at("*");

17 ();

18 }

19 for (int outerIndex=0;outerIndex<=OUTER_ITERATION;outerIndex++) {

20 StopWatch stopWatch = new LoggingStopWatch("StringBufferConcat");

21 concatTestSb = new StringBuffer();

22 for (int innerIndex=0;innerIndex<=INNER_ITERATION;innerIndex++)

23 nd("*");

24 ();

25 }

26 for (int outerIndex=0;outerIndex<=OUTER_ITERATION;outerIndex++) {

27 StopWatch stopWatch = new LoggingStopWatch("StringBuilderConcat");

28 concatTestSbu = new StringBuilder();

29 for (int innerIndex=0;innerIndex<=INNER_ITERATION;innerIndex++)

30 nd("*");

31 ();

32 }

接下來通過執行程式來生成效能指標。我的執行環境是64位的Windown7作業系統,32位的JVM(7-ea) 帶4GB記憶體,雙核Quad 2.00GHz的'CPU的機器.

經過20次迭代後,我們得到如下的資料:

結果非常完美如我們想象的那樣。唯一比較有趣的事情是為什麼at也很不錯,我們都知道,String是一個常類(初始化後就不會改變的類),那麼為什麼concat的效能會更好一些呢。(譯者注:其實原文作者的測試程式碼有問題,對於concat()方法的測試程式碼應該寫成 concatTestStr=at(“*”)才對。)為了回答這個問題,我們應該看看concat反編譯出來的位元組碼。在本文的下載包裡面包含了所有的位元組碼,但是現在我們先看一下concat的這個程式碼片段:

01 46: new #6; //class java/lang/StringBuilder

02 49: dup

03 50: invokespecial #7; //Method java/lang/StringBuilder."":()V

04 53: aload_1

05 54: invokevirtual #8; //Method java/lang/nd:

06 (Ljava/lang/String;)Ljava/lang/StringBuilder;

07 57: ldc #9; //String *

08 59: invokevirtual #8; //Method java/lang/nd:

09 (Ljava/lang/String;)Ljava/lang/StringBuilder;

10 62: invokevirtual #10; //Method java/lang/ring:()

11 Ljava/lang/String;

12 65: astore_1

13 66: iinc 7, 1

14 69: goto 38

這段程式碼是at()的位元組碼,從這段程式碼中,我們可以清楚的看到,concat()方法使用了 StringBuilder,concat()的效能應該和StringBuilder的一樣好,但是由於額外的建立StringBuilder和做nd(str)nd(str)ring()的操作,使得concate的效能會受到一些影響,所以 StringBuilder和String Cancate的時間是1.8和3.3。

因此,即時在做最簡單的拼接時,如果我們不想建立StringBuffer或StringBuilder例項使,我們也因該使用concat。但是對於大量的字串拼接操作,我們就不應該使用concat(譯者注:因為測試程式碼功能上並不完全等價,更換後的測試程式碼concat的平均處理時間是 1650.9毫秒。這個結果在原文的評論裡面。),因為concat會降低你程式的效能,消耗你的cpu。因此,在不考慮執行緒安全和同步的情況下,為了獲得最高的效能,我們應儘量使用StringBuilder